OLD | NEW |
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_overflow_menu_controlle
r.h" | 23 #include "chrome/browser/views/extensions/browser_action_overflow_menu_controlle
r.h" |
23 #include "chrome/browser/views/extensions/extension_popup.h" | 24 #include "chrome/browser/views/extensions/extension_popup.h" |
24 #include "chrome/browser/views/toolbar_view.h" | 25 #include "chrome/browser/views/toolbar_view.h" |
25 #include "chrome/common/notification_source.h" | 26 #include "chrome/common/notification_source.h" |
26 #include "chrome/common/notification_type.h" | 27 #include "chrome/common/notification_type.h" |
27 #include "chrome/common/pref_names.h" | 28 #include "chrome/common/pref_names.h" |
28 #include "grit/app_resources.h" | 29 #include "grit/app_resources.h" |
29 #include "third_party/skia/include/core/SkBitmap.h" | 30 #include "third_party/skia/include/core/SkBitmap.h" |
30 #include "third_party/skia/include/core/SkTypeface.h" | 31 #include "third_party/skia/include/core/SkTypeface.h" |
31 #include "third_party/skia/include/effects/SkGradientShader.h" | 32 #include "third_party/skia/include/effects/SkGradientShader.h" |
32 #include "views/controls/button/menu_button.h" | 33 #include "views/controls/button/menu_button.h" |
33 #include "views/controls/button/text_button.h" | 34 #include "views/controls/button/text_button.h" |
34 #include "views/window/window.h" | 35 #include "views/window/window.h" |
35 | 36 |
36 #include "grit/theme_resources.h" | 37 #include "grit/theme_resources.h" |
37 | 38 |
38 // The size (both dimensions) of the buttons for page actions. | 39 // The size (both dimensions) of the buttons for page actions. |
39 static const int kButtonSize = 29; | 40 static const int kButtonSize = 29; |
40 | 41 |
41 // The padding between the browser actions and the OmniBox/page menu. | 42 // The padding between the browser actions and the OmniBox/page menu. |
42 static const int kHorizontalPadding = 4; | 43 static const int kHorizontalPadding = 4; |
| 44 static const int kHorizontalPaddingRtl = 8; |
43 | 45 |
44 // The padding between browser action buttons. Visually, the actual number of | 46 // The padding between browser action buttons. Visually, the actual number of |
45 // empty (non-drawing) pixels is this value + 2 when adjacent browser icons | 47 // empty (non-drawing) pixels is this value + 2 when adjacent browser icons |
46 // use their maximum allowed size. | 48 // use their maximum allowed size. |
47 static const int kBrowserActionButtonPadding = 3; | 49 static const int kBrowserActionButtonPadding = 3; |
48 | 50 |
49 // This is the same value from toolbar.cc. We position the browser actions | 51 // This is the same value from toolbar.cc. We position the browser actions |
50 // container flush with the edges of the toolbar as a special case so that we | 52 // container flush with the edges of the toolbar as a special case so that we |
51 // can draw the badge outside the visual bounds of the container. | 53 // can draw the badge outside the visual bounds of the container. |
52 static const int kControlVertOffset = 6; | 54 static const int kControlVertOffset = 6; |
53 | 55 |
54 // The margin between the divider and the chrome menu buttons. | 56 // The margin between the divider and the chrome menu buttons. |
55 static const int kDividerHorizontalMargin = 2; | 57 static const int kDividerHorizontalMargin = 2; |
56 | 58 |
57 // The padding above and below the divider. | 59 // The padding above and below the divider. |
58 static const int kDividerVerticalPadding = 9; | 60 static const int kDividerVerticalPadding = 9; |
59 | 61 |
60 // The margin above the chevron. | 62 // The margin above the chevron. |
61 static const int kChevronTopMargin = 9; | 63 static const int kChevronTopMargin = 9; |
62 | 64 |
63 // The margin to the right of the chevron. | 65 // The margin to the right of the chevron. |
64 static const int kChevronRightMargin = 4; | 66 static const int kChevronRightMargin = 4; |
65 | 67 |
66 // Extra hit-area for the resize gripper. | 68 // Extra hit-area for the resize gripper. |
67 static const int kExtraResizeArea = 4; | 69 static const int kExtraResizeArea = 4; |
68 | 70 |
| 71 // Width of the drop indicator. |
| 72 static const int kDropIndicatorWidth = 2; |
| 73 |
| 74 // Color of the drop indicator. |
| 75 static const SkColor kDropIndicatorColor = SK_ColorBLACK; |
| 76 |
| 77 // The x offset for the drop indicator (how much we shift it by). |
| 78 static const int kDropIndicatorOffsetLtr = 3; |
| 79 static const int kDropIndicatorOffsetRtl = 9; |
| 80 |
69 //////////////////////////////////////////////////////////////////////////////// | 81 //////////////////////////////////////////////////////////////////////////////// |
70 // BrowserActionButton | 82 // BrowserActionButton |
71 | 83 |
72 BrowserActionButton::BrowserActionButton(Extension* extension, | 84 BrowserActionButton::BrowserActionButton(Extension* extension, |
73 BrowserActionsContainer* panel) | 85 BrowserActionsContainer* panel) |
74 : MenuButton(this, L"", NULL, false), | 86 : MenuButton(this, L"", NULL, false), |
75 browser_action_(extension->browser_action()), | 87 browser_action_(extension->browser_action()), |
76 extension_(extension), | 88 extension_(extension), |
77 tracker_(NULL), | 89 tracker_(NULL), |
78 showing_context_menu_(false), | 90 showing_context_menu_(false), |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 } | 263 } |
252 | 264 |
253 | 265 |
254 //////////////////////////////////////////////////////////////////////////////// | 266 //////////////////////////////////////////////////////////////////////////////// |
255 // BrowserActionView | 267 // BrowserActionView |
256 | 268 |
257 BrowserActionView::BrowserActionView(Extension* extension, | 269 BrowserActionView::BrowserActionView(Extension* extension, |
258 BrowserActionsContainer* panel) | 270 BrowserActionsContainer* panel) |
259 : panel_(panel) { | 271 : panel_(panel) { |
260 button_ = new BrowserActionButton(extension, panel); | 272 button_ = new BrowserActionButton(extension, panel); |
| 273 button_->SetDragController(panel_); |
261 AddChildView(button_); | 274 AddChildView(button_); |
262 button_->UpdateState(); | 275 button_->UpdateState(); |
263 } | 276 } |
264 | 277 |
265 void BrowserActionView::Layout() { | 278 void BrowserActionView::Layout() { |
266 button_->SetBounds(0, kControlVertOffset, width(), kButtonSize); | 279 button_->SetBounds(0, kControlVertOffset, width(), kButtonSize); |
267 } | 280 } |
268 | 281 |
269 void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { | 282 void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { |
270 View::PaintChildren(canvas); | 283 View::PaintChildren(canvas); |
(...skipping 13 matching lines...) Expand all Loading... |
284 : profile_(profile), | 297 : profile_(profile), |
285 toolbar_(toolbar), | 298 toolbar_(toolbar), |
286 popup_(NULL), | 299 popup_(NULL), |
287 popup_button_(NULL), | 300 popup_button_(NULL), |
288 model_(NULL), | 301 model_(NULL), |
289 resize_gripper_(NULL), | 302 resize_gripper_(NULL), |
290 chevron_(NULL), | 303 chevron_(NULL), |
291 suppress_chevron_(false), | 304 suppress_chevron_(false), |
292 resize_amount_(0), | 305 resize_amount_(0), |
293 animation_target_size_(0), | 306 animation_target_size_(0), |
| 307 drop_indicator_position_(-1), |
294 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { | 308 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { |
295 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); | 309 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); |
296 | 310 |
297 ExtensionsService* extension_service = profile->GetExtensionsService(); | 311 ExtensionsService* extension_service = profile->GetExtensionsService(); |
298 if (!extension_service) // The |extension_service| can be NULL in Incognito. | 312 if (!extension_service) // The |extension_service| can be NULL in Incognito. |
299 return; | 313 return; |
300 | 314 |
301 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, | 315 registrar_.Add(this, NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE, |
302 Source<Profile>(profile_)); | 316 Source<Profile>(profile_)); |
303 | 317 |
(...skipping 10 matching lines...) Expand all Loading... |
314 SkBitmap* chevron_image = rb.GetBitmapNamed(IDR_BOOKMARK_BAR_CHEVRONS); | 328 SkBitmap* chevron_image = rb.GetBitmapNamed(IDR_BOOKMARK_BAR_CHEVRONS); |
315 chevron_ = new views::MenuButton(NULL, std::wstring(), this, false); | 329 chevron_ = new views::MenuButton(NULL, std::wstring(), this, false); |
316 chevron_->SetVisible(false); | 330 chevron_->SetVisible(false); |
317 chevron_->SetIcon(*chevron_image); | 331 chevron_->SetIcon(*chevron_image); |
318 // Chevron contains >> that should point left in LTR locales. | 332 // Chevron contains >> that should point left in LTR locales. |
319 chevron_->EnableCanvasFlippingForRTLUI(true); | 333 chevron_->EnableCanvasFlippingForRTLUI(true); |
320 AddChildView(chevron_); | 334 AddChildView(chevron_); |
321 | 335 |
322 int predefined_width = | 336 int predefined_width = |
323 profile_->GetPrefs()->GetInteger(prefs::kBrowserActionContainerWidth); | 337 profile_->GetPrefs()->GetInteger(prefs::kBrowserActionContainerWidth); |
| 338 if (predefined_width == 0) { |
| 339 // The width will never be 0 (due to container min size restriction) |
| 340 // 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 predefined_width = IconCountToWidth(model_->size()); |
| 343 } |
324 container_size_ = gfx::Size(predefined_width, kButtonSize); | 344 container_size_ = gfx::Size(predefined_width, kButtonSize); |
325 } | 345 } |
326 | 346 |
327 BrowserActionsContainer::~BrowserActionsContainer() { | 347 BrowserActionsContainer::~BrowserActionsContainer() { |
328 if (model_) | 348 if (model_) |
329 model_->RemoveObserver(this); | 349 model_->RemoveObserver(this); |
330 CloseOverflowMenu(); | 350 CloseOverflowMenu(); |
331 HidePopup(); | 351 HidePopup(); |
332 DeleteBrowserActionViews(); | 352 DeleteBrowserActionViews(); |
333 } | 353 } |
(...skipping 27 matching lines...) Expand all Loading... |
361 for (size_t i = 0; i < browser_action_views_.size(); ++i) | 381 for (size_t i = 0; i < browser_action_views_.size(); ++i) |
362 browser_action_views_[i]->button()->UpdateState(); | 382 browser_action_views_[i]->button()->UpdateState(); |
363 } | 383 } |
364 | 384 |
365 void BrowserActionsContainer::CloseOverflowMenu() { | 385 void BrowserActionsContainer::CloseOverflowMenu() { |
366 // Close the overflow menu if open (and the context menu off of that). | 386 // Close the overflow menu if open (and the context menu off of that). |
367 if (overflow_menu_.get()) | 387 if (overflow_menu_.get()) |
368 overflow_menu_->CancelMenu(); | 388 overflow_menu_->CancelMenu(); |
369 } | 389 } |
370 | 390 |
| 391 void BrowserActionsContainer::CreateBrowserActionViews() { |
| 392 DCHECK(browser_action_views_.empty()); |
| 393 for (ExtensionList::iterator iter = model_->begin(); |
| 394 iter != model_->end(); ++iter) { |
| 395 BrowserActionView* view = new BrowserActionView(*iter, this); |
| 396 browser_action_views_.push_back(view); |
| 397 AddChildView(view); |
| 398 } |
| 399 } |
| 400 |
371 void BrowserActionsContainer::DeleteBrowserActionViews() { | 401 void BrowserActionsContainer::DeleteBrowserActionViews() { |
372 if (!browser_action_views_.empty()) { | 402 if (!browser_action_views_.empty()) { |
373 for (size_t i = 0; i < browser_action_views_.size(); ++i) | 403 for (size_t i = 0; i < browser_action_views_.size(); ++i) |
374 RemoveChildView(browser_action_views_[i]); | 404 RemoveChildView(browser_action_views_[i]); |
375 STLDeleteContainerPointers(browser_action_views_.begin(), | 405 STLDeleteContainerPointers(browser_action_views_.begin(), |
376 browser_action_views_.end()); | 406 browser_action_views_.end()); |
377 browser_action_views_.clear(); | 407 browser_action_views_.clear(); |
378 } | 408 } |
379 } | 409 } |
380 | 410 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 return gfx::Size(0, 0); | 496 return gfx::Size(0, 0); |
467 | 497 |
468 // We calculate the size of the view by taking the current width and | 498 // We calculate the size of the view by taking the current width and |
469 // subtracting resize_amount_ (the latter represents how far the user is | 499 // subtracting resize_amount_ (the latter represents how far the user is |
470 // resizing the view or, if animating the snapping, how far to animate it). | 500 // resizing the view or, if animating the snapping, how far to animate it). |
471 // But we also clamp it to a minimum size and the maximum size, so that the | 501 // But we also clamp it to a minimum size and the maximum size, so that the |
472 // container can never shrink too far or take up more space than it needs. In | 502 // container can never shrink too far or take up more space than it needs. In |
473 // other words: ContainerMinSize() < width() - resize < ClampTo(MAX). | 503 // other words: ContainerMinSize() < width() - resize < ClampTo(MAX). |
474 int width = std::max(ContainerMinSize(), | 504 int width = std::max(ContainerMinSize(), |
475 container_size_.width() - resize_amount_); | 505 container_size_.width() - resize_amount_); |
476 int max_width = ClampToNearestIconCount(-1); // -1 gives max width. | 506 int max_width = ClampToNearestIconCount(-1, false); // -1 gives max width. |
477 width = std::min(width, max_width); | 507 width = std::min(width, max_width); |
478 | 508 |
479 return gfx::Size(width, kButtonSize); | 509 return gfx::Size(width, kButtonSize); |
480 } | 510 } |
481 | 511 |
482 void BrowserActionsContainer::Layout() { | 512 void BrowserActionsContainer::Layout() { |
483 if (!resize_gripper_ || !chevron_) | 513 if (!resize_gripper_ || !chevron_) |
484 return; // These classes are not created in Incognito mode. | 514 return; // These classes are not created in Incognito mode. |
485 if (browser_action_views_.size() == 0) { | 515 if (browser_action_views_.size() == 0) { |
486 resize_gripper_->SetVisible(false); | 516 resize_gripper_->SetVisible(false); |
487 chevron_->SetVisible(false); | 517 chevron_->SetVisible(false); |
488 return; | 518 return; |
489 } | 519 } |
490 | 520 |
491 int x = 0; | 521 int x = 0; |
492 if (resize_gripper_->IsVisible()) { | 522 if (resize_gripper_->IsVisible()) { |
493 // We'll draw the resize gripper a little wider, to add some invisible hit | 523 // We'll draw the resize gripper a little wider, to add some invisible hit |
494 // target area - but we don't account for it anywhere. | 524 // target area - but we don't account for it anywhere. |
495 gfx::Size sz = resize_gripper_->GetPreferredSize(); | 525 gfx::Size sz = resize_gripper_->GetPreferredSize(); |
496 resize_gripper_->SetBounds(x, (height() - sz.height()) / 2 + 1, | 526 resize_gripper_->SetBounds(x, (height() - sz.height()) / 2 + 1, |
497 sz.width() + kExtraResizeArea, sz.height()); | 527 sz.width() + kExtraResizeArea, sz.height()); |
498 x += sz.width(); | 528 x += sz.width(); |
499 } | 529 } |
500 | 530 |
501 x += kHorizontalPadding; | 531 x += UILayoutIsRightToLeft() ? kHorizontalPaddingRtl : kHorizontalPadding; |
502 | 532 |
503 // Calculate if all icons fit without showing the chevron. We need to know | 533 // Calculate if all icons fit without showing the chevron. We need to know |
504 // this beforehand, because showing the chevron will decrease the space that | 534 // this beforehand, because showing the chevron will decrease the space that |
505 // we have to draw the visible ones (ie. if one icon is visible and another | 535 // we have to draw the visible ones (ie. if one icon is visible and another |
506 // doesn't have enough room). | 536 // doesn't have enough room). |
507 int last_x_of_icons = x + | 537 int last_x_of_icons = x + |
508 (browser_action_views_.size() * kButtonSize) + | 538 (browser_action_views_.size() * kButtonSize) + |
509 ((browser_action_views_.size() - 1) * | 539 ((browser_action_views_.size() - 1) * |
510 kBrowserActionButtonPadding); | 540 kBrowserActionButtonPadding); |
511 | 541 |
(...skipping 30 matching lines...) Expand all Loading... |
542 | 572 |
543 void BrowserActionsContainer::Paint(gfx::Canvas* canvas) { | 573 void BrowserActionsContainer::Paint(gfx::Canvas* canvas) { |
544 // The one-pixel themed vertical divider to the right of the browser actions. | 574 // The one-pixel themed vertical divider to the right of the browser actions. |
545 int x = UILayoutIsRightToLeft() ? kDividerHorizontalMargin : | 575 int x = UILayoutIsRightToLeft() ? kDividerHorizontalMargin : |
546 width() - kDividerHorizontalMargin; | 576 width() - kDividerHorizontalMargin; |
547 DetachableToolbarView::PaintVerticalDivider( | 577 DetachableToolbarView::PaintVerticalDivider( |
548 canvas, x, height(), kDividerVerticalPadding, | 578 canvas, x, height(), kDividerVerticalPadding, |
549 DetachableToolbarView::kEdgeDividerColor, | 579 DetachableToolbarView::kEdgeDividerColor, |
550 DetachableToolbarView::kMiddleDividerColor, | 580 DetachableToolbarView::kMiddleDividerColor, |
551 GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR)); | 581 GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR)); |
| 582 |
| 583 // The two-pixel width drop indicator. |
| 584 if (drop_indicator_position_ > -1) { |
| 585 x = drop_indicator_position_; |
| 586 int y = kDividerVerticalPadding; |
| 587 gfx::Rect indicator_bounds(x - kDropIndicatorWidth / 2, |
| 588 y, |
| 589 kDropIndicatorWidth, |
| 590 height() - (2 * kDividerVerticalPadding)); |
| 591 |
| 592 // TODO(sky/glen): make me pretty! |
| 593 canvas->FillRectInt(kDropIndicatorColor, indicator_bounds.x(), |
| 594 indicator_bounds.y(), indicator_bounds.width(), |
| 595 indicator_bounds.height()); |
| 596 } |
552 } | 597 } |
553 | 598 |
554 void BrowserActionsContainer::ViewHierarchyChanged(bool is_add, | 599 void BrowserActionsContainer::ViewHierarchyChanged(bool is_add, |
555 views::View* parent, | 600 views::View* parent, |
556 views::View* child) { | 601 views::View* child) { |
557 // No extensions (e.g., incognito). | 602 // No extensions (e.g., incognito). |
558 if (!model_) | 603 if (!model_) |
559 return; | 604 return; |
560 | 605 |
561 if (is_add && child == this) { | 606 if (is_add && child == this) { |
562 // Initial toolbar button creation and placement in the widget hierarchy. | 607 // Initial toolbar button creation and placement in the widget hierarchy. |
563 // We do this here instead of in the constructor because AddBrowserAction | 608 // We do this here instead of in the constructor because AddBrowserAction |
564 // calls Layout on the Toolbar, which needs this object to be constructed | 609 // calls Layout on the Toolbar, which needs this object to be constructed |
565 // before its Layout function is called. | 610 // before its Layout function is called. |
566 for (ExtensionList::iterator iter = model_->begin(); | 611 CreateBrowserActionViews(); |
567 iter != model_->end(); ++iter) { | |
568 BrowserActionView* view = new BrowserActionView(*iter, this); | |
569 browser_action_views_.push_back(view); | |
570 AddChildView(view); | |
571 } | |
572 } | 612 } |
573 } | 613 } |
574 | 614 |
| 615 bool BrowserActionsContainer::GetDropFormats( |
| 616 int* formats, std::set<OSExchangeData::CustomFormat>* custom_formats) { |
| 617 custom_formats->insert(BrowserActionDragData::GetBrowserActionCustomFormat()); |
| 618 return true; |
| 619 } |
| 620 |
| 621 bool BrowserActionsContainer::AreDropTypesRequired() { |
| 622 return true; |
| 623 } |
| 624 |
| 625 bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { |
| 626 BrowserActionDragData drop_data; |
| 627 if (!drop_data.Read(data)) |
| 628 return false; |
| 629 return drop_data.IsFromProfile(profile_); |
| 630 } |
| 631 |
| 632 void BrowserActionsContainer::OnDragEntered( |
| 633 const views::DropTargetEvent& event) { |
| 634 } |
| 635 |
| 636 int BrowserActionsContainer::OnDragUpdated( |
| 637 const views::DropTargetEvent& event) { |
| 638 // 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 |
| 640 // clamping affects where the drop indicator is drawn. |
| 641 |
| 642 // 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 |
| 644 // left of that button to the right of that button. |
| 645 int x = event.x() + (kButtonSize / 2) + (2 * kBrowserActionButtonPadding); |
| 646 if (chevron_->IsVisible()) |
| 647 x += chevron_->bounds().width(); |
| 648 x = ClampToNearestIconCount(x, false); |
| 649 |
| 650 if (!UILayoutIsRightToLeft() && chevron_->IsVisible()) { |
| 651 // 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 |
| 653 // RTL it is on the left and we always want to count the width. |
| 654 x -= chevron_->width(); |
| 655 } |
| 656 |
| 657 // 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 |
| 659 // buttons. |
| 660 drop_indicator_position_ = x - kBrowserActionButtonPadding - |
| 661 (UILayoutIsRightToLeft() ? kDropIndicatorOffsetRtl : |
| 662 kDropIndicatorOffsetLtr); |
| 663 |
| 664 SchedulePaint(); |
| 665 return DragDropTypes::DRAG_MOVE; |
| 666 } |
| 667 |
| 668 void BrowserActionsContainer::OnDragExited() { |
| 669 drop_indicator_position_ = -1; |
| 670 SchedulePaint(); |
| 671 } |
| 672 |
| 673 int BrowserActionsContainer::OnPerformDrop( |
| 674 const views::DropTargetEvent& event) { |
| 675 BrowserActionDragData data; |
| 676 if (!data.Read(event.GetData())) |
| 677 return DragDropTypes::DRAG_NONE; |
| 678 |
| 679 // Make sure we have the same view as we started with. |
| 680 DCHECK(browser_action_views_[data.index()]->button()->extension()->id() == |
| 681 data.id()); |
| 682 |
| 683 Extension* dragging = |
| 684 browser_action_views_[data.index()]->button()->extension(); |
| 685 |
| 686 int target_x = drop_indicator_position_; |
| 687 |
| 688 size_t i = 0; |
| 689 for (; i < browser_action_views_.size(); ++i) { |
| 690 int view_x = |
| 691 browser_action_views_[i]->GetBounds(APPLY_MIRRORING_TRANSFORMATION).x(); |
| 692 if (!browser_action_views_[i]->IsVisible() || |
| 693 (UILayoutIsRightToLeft() ? view_x < target_x : view_x >= target_x)) { |
| 694 // We have reached the end of the visible icons or found one that has a |
| 695 // higher x position than the drop point. |
| 696 break; |
| 697 } |
| 698 } |
| 699 |
| 700 // |i| now points to the item to the right of the drop indicator*, which is |
| 701 // correct when dragging an icon to the left. When dragging to the right, |
| 702 // however, we want the icon being dragged to get the index of the item to |
| 703 // the left of the drop indicator, so we subtract one. |
| 704 // * Well, it can also point to the end, but not when dragging to the left. :) |
| 705 if (i > data.index()) |
| 706 --i; |
| 707 |
| 708 model_->MoveBrowserAction(dragging, i); |
| 709 |
| 710 OnDragExited(); // Perform clean up after dragging. |
| 711 return DragDropTypes::DRAG_MOVE; |
| 712 } |
| 713 |
575 void BrowserActionsContainer::Observe(NotificationType type, | 714 void BrowserActionsContainer::Observe(NotificationType type, |
576 const NotificationSource& source, | 715 const NotificationSource& source, |
577 const NotificationDetails& details) { | 716 const NotificationDetails& details) { |
578 switch (type.value) { | 717 switch (type.value) { |
579 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: | 718 case NotificationType::EXTENSION_HOST_VIEW_SHOULD_CLOSE: |
580 // If we aren't the host of the popup, then disregard the notification. | 719 // If we aren't the host of the popup, then disregard the notification. |
581 if (!popup_ || Details<ExtensionHost>(popup_->host()) != details) | 720 if (!popup_ || Details<ExtensionHost>(popup_->host()) != details) |
582 return; | 721 return; |
583 | 722 |
584 HidePopup(); | 723 HidePopup(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 } | 771 } |
633 | 772 |
634 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) { | 773 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) { |
635 if (source == chevron_) { | 774 if (source == chevron_) { |
636 overflow_menu_.reset(new BrowserActionOverflowMenuController( | 775 overflow_menu_.reset(new BrowserActionOverflowMenuController( |
637 this, chevron_, browser_action_views_, VisibleBrowserActions())); | 776 this, chevron_, browser_action_views_, VisibleBrowserActions())); |
638 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow()); | 777 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow()); |
639 } | 778 } |
640 } | 779 } |
641 | 780 |
642 int BrowserActionsContainer::ClampToNearestIconCount(int pixelWidth) const { | 781 void BrowserActionsContainer::WriteDragData( |
| 782 View* sender, int press_x, int press_y, OSExchangeData* data) { |
| 783 DCHECK(data); |
| 784 |
| 785 for (size_t i = 0; i < browser_action_views_.size(); ++i) { |
| 786 if (browser_action_views_[i]->button() == sender) { |
| 787 BrowserActionDragData drag_data( |
| 788 browser_action_views_[i]->button()->extension()->id(), i); |
| 789 drag_data.Write(profile_, data); |
| 790 break; |
| 791 } |
| 792 } |
| 793 } |
| 794 |
| 795 int BrowserActionsContainer::GetDragOperations(View* sender, int x, int y) { |
| 796 return DragDropTypes::DRAG_MOVE; |
| 797 } |
| 798 |
| 799 bool BrowserActionsContainer::CanStartDrag( |
| 800 View* sender, int press_x, int press_y, int x, int y) { |
| 801 return true; |
| 802 } |
| 803 |
| 804 int BrowserActionsContainer::ClampToNearestIconCount( |
| 805 int pixelWidth, bool allow_shrink_to_minimum) const { |
643 // Calculate the width of one icon. | 806 // Calculate the width of one icon. |
644 int icon_width = (kButtonSize + kBrowserActionButtonPadding); | 807 int icon_width = (kButtonSize + kBrowserActionButtonPadding); |
645 | 808 |
646 // Calculate pixel count for the area not used by the icons. | 809 // Calculate pixel count for the area not used by the icons. |
647 int extras = WidthOfNonIconArea(); | 810 int extras = WidthOfNonIconArea(); |
648 | 811 |
649 size_t icon_count = 0u; | 812 size_t icon_count = 0u; |
650 if (pixelWidth >= 0) { | 813 if (pixelWidth >= 0) { |
651 // Caller wants to know how many icons fit within a given space so we start | 814 // Caller wants to know how many icons fit within a given space so we start |
652 // by subtracting the padding, gripper and dividers. | 815 // by subtracting the padding, gripper and dividers. |
653 int icon_area = pixelWidth - extras; | 816 int icon_area = pixelWidth - extras; |
654 icon_area = std::max(0, icon_area); | 817 icon_area = std::max(0, icon_area); |
655 | 818 |
656 // Make sure we never throw an icon into the chevron menu just because | 819 // Make sure we never throw an icon into the chevron menu just because |
657 // there isn't enough enough space for the invisible padding around buttons. | 820 // there isn't enough enough space for the invisible padding around buttons. |
658 icon_area += kBrowserActionButtonPadding - 1; | 821 icon_area += kBrowserActionButtonPadding - 1; |
659 | 822 |
660 // Count the number of icons that fit within that area. | 823 // Count the number of icons that fit within that area. |
661 icon_count = icon_area / icon_width; | 824 icon_count = icon_area / icon_width; |
662 | 825 |
663 // No use allowing more than what we have. | 826 if (icon_count == 0 && allow_shrink_to_minimum) { |
664 if (icon_count > browser_action_views_.size()) | 827 extras = ContainerMinSize(); // Allow very narrow width if no icons. |
| 828 } else if (icon_count > browser_action_views_.size()) { |
| 829 // No use allowing more than what we have. |
665 icon_count = browser_action_views_.size(); | 830 icon_count = browser_action_views_.size(); |
666 else if (icon_count == 0) | 831 } |
667 extras = ContainerMinSize(); // Allow very narrow width if no icons. | |
668 } else { | 832 } else { |
669 // A negative |pixels| count indicates caller wants to know the max width | 833 // A negative |pixels| count indicates caller wants to know the max width |
670 // that fits all icons; | 834 // that fits all icons; |
671 icon_count = browser_action_views_.size(); | 835 icon_count = browser_action_views_.size(); |
672 } | 836 } |
673 | 837 |
674 int returning = extras + (icon_count * icon_width); | 838 return extras + (icon_count * icon_width); |
675 return returning; | |
676 } | 839 } |
677 | 840 |
678 void BrowserActionsContainer::BrowserActionAdded(Extension* extension, | 841 void BrowserActionsContainer::BrowserActionAdded(Extension* extension, |
679 int index) { | 842 int index) { |
680 #if defined(DEBUG) | 843 #if defined(DEBUG) |
681 for (size_t i = 0; i < browser_action_views_.size(); ++i) { | 844 for (size_t i = 0; i < browser_action_views_.size(); ++i) { |
682 DCHECK(browser_action_views_[i]->button()->extension() != extension) << | 845 DCHECK(browser_action_views_[i]->button()->extension() != extension) << |
683 "Asked to add a browser action view for an extension that already " | 846 "Asked to add a browser action view for an extension that already " |
684 "exists."; | 847 "exists."; |
685 } | 848 } |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 | 901 |
739 // For details on why we do the following see the class comments in the | 902 // For details on why we do the following see the class comments in the |
740 // header. | 903 // header. |
741 | 904 |
742 // Calculate the target size we'll animate to (end state). This might be | 905 // Calculate the target size we'll animate to (end state). This might be |
743 // the same size (if the icon we are removing is in the overflow bucket | 906 // the same size (if the icon we are removing is in the overflow bucket |
744 // and there are other icons there). We don't decrement visible_actions | 907 // and there are other icons there). We don't decrement visible_actions |
745 // because we want the container to stay the same size (clamping will take | 908 // because we want the container to stay the same size (clamping will take |
746 // care of shrinking the container if there aren't enough icons to show). | 909 // care of shrinking the container if there aren't enough icons to show). |
747 animation_target_size_ = | 910 animation_target_size_ = |
748 ClampToNearestIconCount(IconCountToWidth(visible_actions)); | 911 ClampToNearestIconCount(IconCountToWidth(visible_actions), true); |
749 | 912 |
750 // Animate! | 913 // Animate! |
751 resize_animation_->Reset(); | 914 resize_animation_->Reset(); |
752 resize_animation_->SetTweenType(SlideAnimation::EASE_OUT); | 915 resize_animation_->SetTweenType(SlideAnimation::EASE_OUT); |
753 resize_animation_->Show(); | 916 resize_animation_->Show(); |
754 return; | 917 return; |
755 } | 918 } |
756 } | 919 } |
757 } | 920 } |
758 | 921 |
| 922 void BrowserActionsContainer::BrowserActionMoved(Extension* extension, |
| 923 int index) { |
| 924 DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); |
| 925 |
| 926 DeleteBrowserActionViews(); |
| 927 CreateBrowserActionViews(); |
| 928 Layout(); |
| 929 } |
| 930 |
759 int BrowserActionsContainer::WidthOfNonIconArea() const { | 931 int BrowserActionsContainer::WidthOfNonIconArea() const { |
760 int chevron_size = (chevron_->IsVisible()) ? | 932 int chevron_size = (chevron_->IsVisible()) ? |
761 chevron_->GetPreferredSize().width() : 0; | 933 chevron_->GetPreferredSize().width() : 0; |
762 return resize_gripper_->GetPreferredSize().width() + kHorizontalPadding + | 934 int padding = UILayoutIsRightToLeft() ? kHorizontalPaddingRtl : |
| 935 kHorizontalPadding; |
| 936 return resize_gripper_->GetPreferredSize().width() + padding + |
763 chevron_size + kChevronRightMargin + kDividerHorizontalMargin; | 937 chevron_size + kChevronRightMargin + kDividerHorizontalMargin; |
764 } | 938 } |
765 | 939 |
766 int BrowserActionsContainer::IconCountToWidth(int icons) const { | 940 int BrowserActionsContainer::IconCountToWidth(int icons) const { |
767 DCHECK(icons >= 0); | 941 DCHECK(icons >= 0); |
768 if (icons == 0) | 942 if (icons == 0) |
769 return ContainerMinSize(); | 943 return ContainerMinSize(); |
770 | 944 |
771 int icon_width = kButtonSize + kBrowserActionButtonPadding; | 945 int icon_width = kButtonSize + kBrowserActionButtonPadding; |
772 | 946 |
(...skipping 18 matching lines...) Expand all Loading... |
791 if (!done_resizing) { | 965 if (!done_resizing) { |
792 resize_amount_ = resize_amount; | 966 resize_amount_ = resize_amount; |
793 OnBrowserActionVisibilityChanged(); | 967 OnBrowserActionVisibilityChanged(); |
794 } else { | 968 } else { |
795 // For details on why we do the following see the class comments in the | 969 // For details on why we do the following see the class comments in the |
796 // header. | 970 // header. |
797 | 971 |
798 // Clamp lower limit to 0 and upper limit to the amount that allows enough | 972 // Clamp lower limit to 0 and upper limit to the amount that allows enough |
799 // room for all icons to show. | 973 // room for all icons to show. |
800 int new_width = std::max(0, container_size_.width() - resize_amount); | 974 int new_width = std::max(0, container_size_.width() - resize_amount); |
801 int max_width = ClampToNearestIconCount(-1); | 975 int max_width = ClampToNearestIconCount(-1, false); |
802 new_width = std::min(new_width, max_width); | 976 new_width = std::min(new_width, max_width); |
803 | 977 |
804 // Up until now we've only been modifying the resize_amount, but now it is | 978 // Up until now we've only been modifying the resize_amount, but now it is |
805 // time to set the container size to the size we have resized to, but then | 979 // time to set the container size to the size we have resized to, but then |
806 // animate to the nearest icon count size (or down to min size if no icon). | 980 // animate to the nearest icon count size (or down to min size if no icon). |
807 container_size_.set_width(new_width); | 981 container_size_.set_width(new_width); |
808 animation_target_size_ = ClampToNearestIconCount(new_width); | 982 animation_target_size_ = ClampToNearestIconCount(new_width, true); |
809 resize_animation_->Reset(); | 983 resize_animation_->Reset(); |
810 resize_animation_->SetTweenType(SlideAnimation::EASE_OUT); | 984 resize_animation_->SetTweenType(SlideAnimation::EASE_OUT); |
811 resize_animation_->Show(); | 985 resize_animation_->Show(); |
812 } | 986 } |
813 } | 987 } |
814 | 988 |
815 void BrowserActionsContainer::AnimationProgressed(const Animation* animation) { | 989 void BrowserActionsContainer::AnimationProgressed(const Animation* animation) { |
816 DCHECK(animation == resize_animation_.get()); | 990 DCHECK(animation == resize_animation_.get()); |
817 | 991 |
818 double e = resize_animation_->GetCurrentValue(); | 992 double e = resize_animation_->GetCurrentValue(); |
819 int difference = container_size_.width() - animation_target_size_; | 993 int difference = container_size_.width() - animation_target_size_; |
820 | 994 |
821 resize_amount_ = static_cast<int>(e * difference); | 995 resize_amount_ = static_cast<int>(e * difference); |
822 | 996 |
823 OnBrowserActionVisibilityChanged(); | 997 OnBrowserActionVisibilityChanged(); |
824 } | 998 } |
825 | 999 |
826 void BrowserActionsContainer::AnimationEnded(const Animation* animation) { | 1000 void BrowserActionsContainer::AnimationEnded(const Animation* animation) { |
827 container_size_.set_width(animation_target_size_); | 1001 container_size_.set_width(animation_target_size_); |
828 animation_target_size_ = 0; | 1002 animation_target_size_ = 0; |
829 resize_amount_ = 0; | 1003 resize_amount_ = 0; |
830 OnBrowserActionVisibilityChanged(); | 1004 OnBrowserActionVisibilityChanged(); |
831 suppress_chevron_ = false; | 1005 suppress_chevron_ = false; |
832 | 1006 |
833 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth, | 1007 profile_->GetPrefs()->SetInteger(prefs::kBrowserActionContainerWidth, |
834 container_size_.width()); | 1008 container_size_.width()); |
835 } | 1009 } |
OLD | NEW |