| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/tabs/tab_strip.h" | 5 #include "chrome/browser/views/tabs/tab_strip.h" |
| 6 | 6 |
| 7 #include "app/drag_drop_types.h" | 7 #include "app/drag_drop_types.h" |
| 8 #include "app/gfx/canvas.h" | 8 #include "app/gfx/canvas.h" |
| 9 #include "app/gfx/path.h" | 9 #include "app/gfx/path.h" |
| 10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 | 492 |
| 493 // TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug. | 493 // TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug. |
| 494 drag_controller_.reset(NULL); | 494 drag_controller_.reset(NULL); |
| 495 | 495 |
| 496 // Make sure we unhook ourselves as a message loop observer so that we don't | 496 // Make sure we unhook ourselves as a message loop observer so that we don't |
| 497 // crash in the case where the user closes the window after closing a tab | 497 // crash in the case where the user closes the window after closing a tab |
| 498 // but before moving the mouse. | 498 // but before moving the mouse. |
| 499 RemoveMessageLoopObserver(); | 499 RemoveMessageLoopObserver(); |
| 500 } | 500 } |
| 501 | 501 |
| 502 int TabStrip::GetPreferredHeight() { | |
| 503 return GetPreferredSize().height(); | |
| 504 } | |
| 505 | |
| 506 bool TabStrip::CanProcessInputEvents() const { | 502 bool TabStrip::CanProcessInputEvents() const { |
| 507 return !IsAnimating(); | 503 return !IsAnimating(); |
| 508 } | 504 } |
| 509 | 505 |
| 510 bool TabStrip::PointIsWithinWindowCaption(const gfx::Point& point) { | |
| 511 views::View* v = GetViewForPoint(point); | |
| 512 | |
| 513 // If there is no control at this location, claim the hit was in the title | |
| 514 // bar to get a move action. | |
| 515 if (v == this) | |
| 516 return true; | |
| 517 | |
| 518 // Check to see if the point is within the non-button parts of the new tab | |
| 519 // button. The button has a non-rectangular shape, so if it's not in the | |
| 520 // visual portions of the button we treat it as a click to the caption. | |
| 521 gfx::Point point_in_newtab_coords(point); | |
| 522 View::ConvertPointToView(this, newtab_button_, &point_in_newtab_coords); | |
| 523 if (newtab_button_->bounds().Contains(point) && | |
| 524 !newtab_button_->HitTest(point_in_newtab_coords)) { | |
| 525 return true; | |
| 526 } | |
| 527 | |
| 528 // All other regions, including the new Tab button, should be considered part | |
| 529 // of the containing Window's client area so that regular events can be | |
| 530 // processed for them. | |
| 531 return false; | |
| 532 } | |
| 533 | |
| 534 bool TabStrip::IsCompatibleWith(TabStrip* other) { | |
| 535 return model_->profile() == other->model()->profile(); | |
| 536 } | |
| 537 | |
| 538 bool TabStrip::IsAnimating() const { | |
| 539 return active_animation_.get() != NULL; | |
| 540 } | |
| 541 | |
| 542 void TabStrip::DestroyDragController() { | 506 void TabStrip::DestroyDragController() { |
| 543 if (IsDragSessionActive()) | 507 if (IsDragSessionActive()) |
| 544 drag_controller_.reset(NULL); | 508 drag_controller_.reset(NULL); |
| 545 } | 509 } |
| 546 | 510 |
| 547 void TabStrip::DestroyDraggedSourceTab(Tab* tab) { | 511 void TabStrip::DestroyDraggedSourceTab(Tab* tab) { |
| 548 // We could be running an animation that references this Tab. | 512 // We could be running an animation that references this Tab. |
| 549 if (active_animation_.get()) | 513 if (active_animation_.get()) |
| 550 active_animation_->Stop(); | 514 active_animation_->Stop(); |
| 551 // Make sure we leave the tab_data_ vector in a consistent state, otherwise | 515 // Make sure we leave the tab_data_ vector in a consistent state, otherwise |
| (...skipping 14 matching lines...) Expand all Loading... |
| 566 // the stopping of the active animation above may have left the TabStrip in a | 530 // the stopping of the active animation above may have left the TabStrip in a |
| 567 // bad (visual) state. | 531 // bad (visual) state. |
| 568 Layout(); | 532 Layout(); |
| 569 } | 533 } |
| 570 | 534 |
| 571 gfx::Rect TabStrip::GetIdealBounds(int index) { | 535 gfx::Rect TabStrip::GetIdealBounds(int index) { |
| 572 DCHECK(index >= 0 && index < GetTabCount()); | 536 DCHECK(index >= 0 && index < GetTabCount()); |
| 573 return tab_data_.at(index).ideal_bounds; | 537 return tab_data_.at(index).ideal_bounds; |
| 574 } | 538 } |
| 575 | 539 |
| 576 void TabStrip::UpdateLoadingAnimations() { | |
| 577 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { | |
| 578 Tab* current_tab = GetTabAt(i); | |
| 579 if (current_tab->closing()) { | |
| 580 --index; | |
| 581 } else { | |
| 582 TabContents* contents = model_->GetTabContentsAt(index); | |
| 583 if (!contents || !contents->is_loading()) { | |
| 584 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE); | |
| 585 } else if (contents->waiting_for_response()) { | |
| 586 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_WAITING); | |
| 587 } else { | |
| 588 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING); | |
| 589 } | |
| 590 } | |
| 591 } | |
| 592 } | |
| 593 | |
| 594 void TabStrip::SetBackgroundOffset(gfx::Point offset) { | |
| 595 int tab_count = GetTabCount(); | |
| 596 for (int i = 0; i < tab_count; ++i) | |
| 597 GetTabAt(i)->SetBackgroundOffset(offset); | |
| 598 } | |
| 599 | |
| 600 void TabStrip::InitTabStripButtons() { | 540 void TabStrip::InitTabStripButtons() { |
| 601 newtab_button_ = new NewTabButton(this); | 541 newtab_button_ = new NewTabButton(this); |
| 602 LoadNewTabButtonImage(); | 542 LoadNewTabButtonImage(); |
| 603 newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB)); | 543 newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB)); |
| 604 AddChildView(newtab_button_); | 544 AddChildView(newtab_button_); |
| 605 } | 545 } |
| 606 | 546 |
| 607 /////////////////////////////////////////////////////////////////////////////// | 547 /////////////////////////////////////////////////////////////////////////////// |
| 608 // TabStrip, views::View overrides: | 548 // TabStrip, views::View overrides: |
| 609 | 549 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 } | 714 } |
| 775 | 715 |
| 776 // No need to do any floating view stuff, we don't use them in the TabStrip. | 716 // No need to do any floating view stuff, we don't use them in the TabStrip. |
| 777 return this; | 717 return this; |
| 778 } | 718 } |
| 779 | 719 |
| 780 void TabStrip::ThemeChanged() { | 720 void TabStrip::ThemeChanged() { |
| 781 LoadNewTabButtonImage(); | 721 LoadNewTabButtonImage(); |
| 782 } | 722 } |
| 783 | 723 |
| 724 void TabStrip::ViewHierarchyChanged(bool is_add, |
| 725 views::View* parent, |
| 726 views::View* child) { |
| 727 if (is_add && child == this) |
| 728 InitTabStripButtons(); |
| 729 } |
| 730 |
| 731 |
| 784 /////////////////////////////////////////////////////////////////////////////// | 732 /////////////////////////////////////////////////////////////////////////////// |
| 785 // TabStrip, TabStripModelObserver implementation: | 733 // TabStrip, TabStripModelObserver implementation: |
| 786 | 734 |
| 787 void TabStrip::TabInsertedAt(TabContents* contents, | 735 void TabStrip::TabInsertedAt(TabContents* contents, |
| 788 int index, | 736 int index, |
| 789 bool foreground) { | 737 bool foreground) { |
| 790 DCHECK(contents); | 738 DCHECK(contents); |
| 791 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); | 739 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); |
| 792 | 740 |
| 793 if (active_animation_.get()) | 741 if (active_animation_.get()) |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 case GDK_MOTION_NOTIFY: | 1024 case GDK_MOTION_NOTIFY: |
| 1077 case GDK_LEAVE_NOTIFY: | 1025 case GDK_LEAVE_NOTIFY: |
| 1078 HandleGlobalMouseMoveEvent(); | 1026 HandleGlobalMouseMoveEvent(); |
| 1079 break; | 1027 break; |
| 1080 default: | 1028 default: |
| 1081 break; | 1029 break; |
| 1082 } | 1030 } |
| 1083 } | 1031 } |
| 1084 #endif | 1032 #endif |
| 1085 | 1033 |
| 1034 //////////////////////////////////////////////////////////////////////////////// |
| 1035 // TabStrip, TabStripWrapper implementation: |
| 1036 |
| 1037 int TabStrip::GetPreferredHeight() { |
| 1038 return GetPreferredSize().height(); |
| 1039 } |
| 1040 |
| 1041 bool TabStrip::IsAnimating() const { |
| 1042 return active_animation_.get() != NULL; |
| 1043 } |
| 1044 |
| 1045 void TabStrip::SetBackgroundOffset(gfx::Point offset) { |
| 1046 int tab_count = GetTabCount(); |
| 1047 for (int i = 0; i < tab_count; ++i) |
| 1048 GetTabAt(i)->SetBackgroundOffset(offset); |
| 1049 } |
| 1050 |
| 1051 bool TabStrip::PointIsWithinWindowCaption(const gfx::Point& point) { |
| 1052 views::View* v = GetViewForPoint(point); |
| 1053 |
| 1054 // If there is no control at this location, claim the hit was in the title |
| 1055 // bar to get a move action. |
| 1056 if (v == this) |
| 1057 return true; |
| 1058 |
| 1059 // Check to see if the point is within the non-button parts of the new tab |
| 1060 // button. The button has a non-rectangular shape, so if it's not in the |
| 1061 // visual portions of the button we treat it as a click to the caption. |
| 1062 gfx::Point point_in_newtab_coords(point); |
| 1063 View::ConvertPointToView(this, newtab_button_, &point_in_newtab_coords); |
| 1064 if (newtab_button_->bounds().Contains(point) && |
| 1065 !newtab_button_->HitTest(point_in_newtab_coords)) { |
| 1066 return true; |
| 1067 } |
| 1068 |
| 1069 // All other regions, including the new Tab button, should be considered part |
| 1070 // of the containing Window's client area so that regular events can be |
| 1071 // processed for them. |
| 1072 return false; |
| 1073 } |
| 1074 |
| 1075 bool TabStrip::IsDragSessionActive() const { |
| 1076 return drag_controller_.get() != NULL; |
| 1077 } |
| 1078 |
| 1079 bool TabStrip::IsCompatibleWith(TabStripWrapper* other) const { |
| 1080 return model_->profile() == other->AsTabStrip()->model()->profile(); |
| 1081 } |
| 1082 |
| 1083 void TabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) { |
| 1084 } |
| 1085 |
| 1086 void TabStrip::UpdateLoadingAnimations() { |
| 1087 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { |
| 1088 Tab* current_tab = GetTabAt(i); |
| 1089 if (current_tab->closing()) { |
| 1090 --index; |
| 1091 } else { |
| 1092 TabContents* contents = model_->GetTabContentsAt(index); |
| 1093 if (!contents || !contents->is_loading()) { |
| 1094 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE); |
| 1095 } else if (contents->waiting_for_response()) { |
| 1096 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_WAITING); |
| 1097 } else { |
| 1098 current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING); |
| 1099 } |
| 1100 } |
| 1101 } |
| 1102 } |
| 1103 |
| 1104 views::View* TabStrip::GetView() { |
| 1105 return this; |
| 1106 } |
| 1107 |
| 1108 BrowserTabStrip* TabStrip::AsBrowserTabStrip() { |
| 1109 return NULL; |
| 1110 } |
| 1111 |
| 1112 TabStrip* TabStrip::AsTabStrip() { |
| 1113 return this; |
| 1114 } |
| 1115 |
| 1086 /////////////////////////////////////////////////////////////////////////////// | 1116 /////////////////////////////////////////////////////////////////////////////// |
| 1087 // TabStrip, private: | 1117 // TabStrip, private: |
| 1088 | 1118 |
| 1089 void TabStrip::Init() { | 1119 void TabStrip::Init() { |
| 1090 model_->AddObserver(this); | 1120 model_->AddObserver(this); |
| 1091 newtab_button_size_.SetSize(kNewTabButtonWidth, kNewTabButtonHeight); | 1121 newtab_button_size_.SetSize(kNewTabButtonWidth, kNewTabButtonHeight); |
| 1092 if (drop_indicator_width == 0) { | 1122 if (drop_indicator_width == 0) { |
| 1093 // Direction doesn't matter, both images are the same size. | 1123 // Direction doesn't matter, both images are the same size. |
| 1094 SkBitmap* drop_image = GetDropArrowImage(true); | 1124 SkBitmap* drop_image = GetDropArrowImage(true); |
| 1095 drop_indicator_width = drop_image->width(); | 1125 drop_indicator_width = drop_image->width(); |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 &TabStrip::ResizeLayoutTabs), | 1631 &TabStrip::ResizeLayoutTabs), |
| 1602 kResizeTabsTimeMs); | 1632 kResizeTabsTimeMs); |
| 1603 } | 1633 } |
| 1604 } else { | 1634 } else { |
| 1605 // Mouse moved quickly out of the tab strip and then into it again, so | 1635 // Mouse moved quickly out of the tab strip and then into it again, so |
| 1606 // cancel the timer so that the strip doesn't move when the mouse moves | 1636 // cancel the timer so that the strip doesn't move when the mouse moves |
| 1607 // back over it. | 1637 // back over it. |
| 1608 resize_layout_factory_.RevokeAll(); | 1638 resize_layout_factory_.RevokeAll(); |
| 1609 } | 1639 } |
| 1610 } | 1640 } |
| OLD | NEW |