diff options
Diffstat (limited to 'chrome/browser/views/tabs')
27 files changed, 47 insertions, 7358 deletions
diff --git a/chrome/browser/views/tabs/base_tab.cc b/chrome/browser/views/tabs/base_tab.cc deleted file mode 100644 index fa752b3..0000000 --- a/chrome/browser/views/tabs/base_tab.cc +++ /dev/null @@ -1,480 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/base_tab.h" - -#include <limits> - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "app/slide_animation.h" -#include "app/theme_provider.h" -#include "app/throb_animation.h" -#include "base/command_line.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/views/tabs/tab_controller.h" -#include "chrome/browser/view_ids.h" -#include "chrome/common/chrome_switches.h" -#include "gfx/canvas_skia.h" -#include "gfx/favicon_size.h" -#include "gfx/font.h" -#include "grit/app_resources.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "views/controls/button/image_button.h" - -#ifdef WIN32 -#include "app/win_util.h" -#endif - -// How long the pulse throb takes. -static const int kPulseDurationMs = 200; - -// How long the hover state takes. -static const int kHoverDurationMs = 90; - -namespace { - -//////////////////////////////////////////////////////////////////////////////// -// TabCloseButton -// -// This is a Button subclass that causes middle clicks to be forwarded to the -// parent View by explicitly not handling them in OnMousePressed. -class TabCloseButton : public views::ImageButton { - public: - explicit TabCloseButton(views::ButtonListener* listener) - : views::ImageButton(listener) { - } - virtual ~TabCloseButton() {} - - virtual bool OnMousePressed(const views::MouseEvent& event) { - bool handled = ImageButton::OnMousePressed(event); - // Explicitly mark midle-mouse clicks as non-handled to ensure the tab - // sees them. - return event.IsOnlyMiddleMouseButton() ? false : handled; - } - - // We need to let the parent know about mouse state so that it - // can highlight itself appropriately. Note that Exit events - // fire before Enter events, so this works. - virtual void OnMouseEntered(const views::MouseEvent& event) { - CustomButton::OnMouseEntered(event); - GetParent()->OnMouseEntered(event); - } - - virtual void OnMouseExited(const views::MouseEvent& event) { - CustomButton::OnMouseExited(event); - GetParent()->OnMouseExited(event); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TabCloseButton); -}; - -} // namespace - -// static -gfx::Font* BaseTab::font_ = NULL; -// static -int BaseTab::font_height_ = 0; - -//////////////////////////////////////////////////////////////////////////////// -// FaviconCrashAnimation -// -// A custom animation subclass to manage the favicon crash animation. -class BaseTab::FavIconCrashAnimation : public LinearAnimation, - public AnimationDelegate { - public: - explicit FavIconCrashAnimation(BaseTab* target) - : ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(1000, 25, this)), - target_(target) { - } - virtual ~FavIconCrashAnimation() {} - - // Animation overrides: - virtual void AnimateToState(double state) { - const double kHidingOffset = 27; - - if (state < .5) { - target_->SetFavIconHidingOffset( - static_cast<int>(floor(kHidingOffset * 2.0 * state))); - } else { - target_->DisplayCrashedFavIcon(); - target_->SetFavIconHidingOffset( - static_cast<int>( - floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); - } - } - - // AnimationDelegate overrides: - virtual void AnimationCanceled(const Animation* animation) { - target_->SetFavIconHidingOffset(0); - } - - private: - BaseTab* target_; - - DISALLOW_COPY_AND_ASSIGN(FavIconCrashAnimation); -}; - -BaseTab::BaseTab(TabController* controller) - : controller_(controller), - closing_(false), - dragging_(false), - loading_animation_frame_(0), - throbber_disabled_(false), - theme_provider_(NULL), - fav_icon_hiding_offset_(0), - should_display_crashed_favicon_(false) { - BaseTab::InitResources(); - - SetID(VIEW_ID_TAB); - - // Add the Close Button. - close_button_ = new TabCloseButton(this); - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - close_button_->SetImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_TAB_CLOSE)); - close_button_->SetImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_TAB_CLOSE_H)); - close_button_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_TAB_CLOSE_P)); - close_button_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_CLOSE_TAB)); - close_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE)); - // Disable animation so that the red danger sign shows up immediately - // to help avoid mis-clicks. - close_button_->SetAnimationDuration(0); - AddChildView(close_button_); - - SetContextMenuController(this); -} - -BaseTab::~BaseTab() { -} - -void BaseTab::SetData(const TabRendererData& data) { - TabRendererData old(data_); - data_ = data; - - if (data_.crashed) { - if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) - StartCrashAnimation(); - } else { - if (IsPerformingCrashAnimation()) - StopCrashAnimation(); - ResetCrashedFavIcon(); - } - - // Sets the accessible name for the tab. - SetAccessibleName(UTF16ToWide(data_.title)); - - DataChanged(old); - - Layout(); -} - -void BaseTab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { - // If this is an extension app and a command line flag is set, - // then disable the throbber. - throbber_disabled_ = data().app && - CommandLine::ForCurrentProcess()->HasSwitch(switches::kAppsNoThrob); - - if (throbber_disabled_) - return; - - if (state == data_.network_state && - state == TabRendererData::NETWORK_STATE_NONE) { - // If the network state is none and hasn't changed, do nothing. Otherwise we - // need to advance the animation frame. - return; - } - - TabRendererData::NetworkState old_state = data_.network_state; - data_.network_state = state; - AdvanceLoadingAnimation(old_state, state); -} - -void BaseTab::StartPulse() { - if (!pulse_animation_.get()) { - pulse_animation_.reset(new ThrobAnimation(this)); - pulse_animation_->SetSlideDuration(kPulseDurationMs); - if (animation_container_.get()) - pulse_animation_->SetContainer(animation_container_.get()); - } - pulse_animation_->Reset(); - pulse_animation_->StartThrobbing(std::numeric_limits<int>::max()); -} - -void BaseTab::StopPulse() { - if (!pulse_animation_.get()) - return; - - pulse_animation_->Stop(); // Do stop so we get notified. - pulse_animation_.reset(NULL); -} - -bool BaseTab::IsSelected() const { - return controller() ? controller()->IsTabSelected(this) : true; -} - -bool BaseTab::IsCloseable() const { - return controller() ? controller()->IsTabCloseable(this) : true; -} - -void BaseTab::OnMouseEntered(const views::MouseEvent& e) { - if (!hover_animation_.get()) { - hover_animation_.reset(new SlideAnimation(this)); - hover_animation_->SetContainer(animation_container_.get()); - hover_animation_->SetSlideDuration(kHoverDurationMs); - } - hover_animation_->SetTweenType(Tween::EASE_OUT); - hover_animation_->Show(); -} - -void BaseTab::OnMouseExited(const views::MouseEvent& e) { - hover_animation_->SetTweenType(Tween::EASE_IN); - hover_animation_->Hide(); -} - -bool BaseTab::OnMousePressed(const views::MouseEvent& event) { - if (!controller()) - return false; - - if (event.IsOnlyLeftMouseButton()) { - // Store whether or not we were selected just now... we only want to be - // able to drag foreground tabs, so we don't start dragging the tab if - // it was in the background. - bool just_selected = !IsSelected(); - if (just_selected) - controller()->SelectTab(this); - controller()->MaybeStartDrag(this, event); - } - return true; -} - -bool BaseTab::OnMouseDragged(const views::MouseEvent& event) { - if (controller()) - controller()->ContinueDrag(event); - return true; -} - -void BaseTab::OnMouseReleased(const views::MouseEvent& event, bool canceled) { - if (!controller()) - return; - - // Notify the drag helper that we're done with any potential drag operations. - // Clean up the drag helper, which is re-created on the next mouse press. - // In some cases, ending the drag will schedule the tab for destruction; if - // so, bail immediately, since our members are already dead and we shouldn't - // do anything else except drop the tab where it is. - if (controller()->EndDrag(canceled)) - return; - - // Close tab on middle click, but only if the button is released over the tab - // (normal windows behavior is to discard presses of a UI element where the - // releases happen off the element). - if (event.IsMiddleMouseButton()) { - if (HitTest(event.location())) { - controller()->CloseTab(this); - } else if (closing_) { - // We're animating closed and a middle mouse button was pushed on us but - // we don't contain the mouse anymore. We assume the user is clicking - // quicker than the animation and we should close the tab that falls under - // the mouse. - BaseTab* closest_tab = controller()->GetTabAt(this, event.location()); - if (closest_tab) - controller()->CloseTab(closest_tab); - } - } -} - -bool BaseTab::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { - if (data_.title.empty()) - return false; - - std::wstring title = UTF16ToWide(data_.title); - // Only show the tooltip if the title is truncated. - if (font_->GetStringWidth(title) > title_bounds().width()) { - *tooltip = title; - return true; - } - return false; -} - -AccessibilityTypes::Role BaseTab::GetAccessibleRole() { - return AccessibilityTypes::ROLE_PAGETAB; -} - -ThemeProvider* BaseTab::GetThemeProvider() { - ThemeProvider* tp = View::GetThemeProvider(); - return tp ? tp : theme_provider_; -} - -void BaseTab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, - TabRendererData::NetworkState state) { - static bool initialized = false; - static int loading_animation_frame_count = 0; - static int waiting_animation_frame_count = 0; - static int waiting_to_loading_frame_count_ratio = 0; - if (!initialized) { - initialized = true; - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap loading_animation(*rb.GetBitmapNamed(IDR_THROBBER)); - loading_animation_frame_count = - loading_animation.width() / loading_animation.height(); - SkBitmap waiting_animation(*rb.GetBitmapNamed(IDR_THROBBER_WAITING)); - waiting_animation_frame_count = - waiting_animation.width() / waiting_animation.height(); - waiting_to_loading_frame_count_ratio = - waiting_animation_frame_count / loading_animation_frame_count; - } - - // The waiting animation is the reverse of the loading animation, but at a - // different rate - the following reverses and scales the animation_frame_ - // so that the frame is at an equivalent position when going from one - // animation to the other. - if (state != old_state) { - loading_animation_frame_ = loading_animation_frame_count - - (loading_animation_frame_ / waiting_to_loading_frame_count_ratio); - } - - if (state != TabRendererData::NETWORK_STATE_NONE) { - loading_animation_frame_ = (loading_animation_frame_ + 1) % - ((state == TabRendererData::NETWORK_STATE_WAITING) ? - waiting_animation_frame_count : loading_animation_frame_count); - } else { - loading_animation_frame_ = 0; - } - SchedulePaint(); -} - -void BaseTab::PaintIcon(gfx::Canvas* canvas, int x, int y) { - if (base::i18n::IsRTL()) { - x = width() - x - - (data().favicon.isNull() ? kFavIconSize : data().favicon.width()); - } - - int favicon_x = x; - if (!data().favicon.isNull() && data().favicon.width() != kFavIconSize) - favicon_x += (data().favicon.width() - kFavIconSize) / 2; - - if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { - ThemeProvider* tp = GetThemeProvider(); - SkBitmap frames(*tp->GetBitmapNamed( - (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ? - IDR_THROBBER_WAITING : IDR_THROBBER)); - int image_size = frames.height(); - int image_offset = loading_animation_frame_ * image_size; - int dst_y = (height() - image_size) / 2; - canvas->DrawBitmapInt(frames, image_offset, 0, image_size, - image_size, favicon_x, dst_y, image_size, image_size, - false); - } else { - canvas->Save(); - canvas->ClipRectInt(0, 0, width(), height()); - if (should_display_crashed_favicon_) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap crashed_fav_icon(*rb.GetBitmapNamed(IDR_SAD_FAVICON)); - canvas->DrawBitmapInt(crashed_fav_icon, 0, 0, crashed_fav_icon.width(), - crashed_fav_icon.height(), favicon_x, - (height() - crashed_fav_icon.height()) / 2 + fav_icon_hiding_offset_, - kFavIconSize, kFavIconSize, true); - } else { - if (!data().favicon.isNull()) { - // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch - // to using that class to render the favicon). - int size = data().favicon.width(); - canvas->DrawBitmapInt(data().favicon, 0, 0, - data().favicon.width(), - data().favicon.height(), - x, y + fav_icon_hiding_offset_, size, size, - true); - } - } - canvas->Restore(); - } -} - -void BaseTab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) { - // Paint the Title. - string16 title = data().title; - if (title.empty()) { - title = data().loading ? - l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : - TabContents::GetDefaultTitle(); - } else { - Browser::FormatTitleForDisplay(&title); - } - - canvas->DrawStringInt(UTF16ToWideHack(title), *font_, title_color, - title_bounds().x(), title_bounds().y(), - title_bounds().width(), title_bounds().height()); -} - -void BaseTab::AnimationProgressed(const Animation* animation) { - SchedulePaint(); -} - -void BaseTab::AnimationCanceled(const Animation* animation) { - SchedulePaint(); -} - -void BaseTab::AnimationEnded(const Animation* animation) { - SchedulePaint(); -} - -void BaseTab::ButtonPressed(views::Button* sender, const views::Event& event) { - DCHECK(sender == close_button_); - controller()->CloseTab(this); -} - -void BaseTab::ShowContextMenu(views::View* source, - const gfx::Point& p, - bool is_mouse_gesture) { - if (controller()) - controller()->ShowContextMenu(this, p); -} - -void BaseTab::SetFavIconHidingOffset(int offset) { - fav_icon_hiding_offset_ = offset; - SchedulePaint(); -} - -void BaseTab::DisplayCrashedFavIcon() { - should_display_crashed_favicon_ = true; -} - -void BaseTab::ResetCrashedFavIcon() { - should_display_crashed_favicon_ = false; -} - -void BaseTab::StartCrashAnimation() { - if (!crash_animation_.get()) - crash_animation_.reset(new FavIconCrashAnimation(this)); - crash_animation_->Stop(); - crash_animation_->Start(); -} - -void BaseTab::StopCrashAnimation() { - if (!crash_animation_.get()) - return; - crash_animation_->Stop(); -} - -bool BaseTab::IsPerformingCrashAnimation() const { - return crash_animation_.get() && crash_animation_->is_animating(); -} - -// static -void BaseTab::InitResources() { - static bool initialized = false; - if (!initialized) { - initialized = true; - font_ = new gfx::Font( - ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); - font_height_ = font_->GetHeight(); - } -} diff --git a/chrome/browser/views/tabs/base_tab.h b/chrome/browser/views/tabs/base_tab.h index 9d6567b..e826fbf 100644 --- a/chrome/browser/views/tabs/base_tab.h +++ b/chrome/browser/views/tabs/base_tab.h @@ -6,199 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_ #pragma once -#include "app/animation.h" -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "chrome/browser/views/tabs/tab_renderer_data.h" -#include "views/controls/button/button.h" -#include "views/view.h" - -class AnimationContainer; -class BaseTab; -class SlideAnimation; -class TabController; -class ThrobAnimation; - -namespace gfx { -class Font; -} // namespace gfx - -namespace views { -class ImageButton; -} // namespace views - -// Base class for tab renderers. -class BaseTab : public AnimationDelegate, - public views::ButtonListener, - public views::ContextMenuController, - public views::View { - public: - explicit BaseTab(TabController* controller); - virtual ~BaseTab(); - - // Sets the data this tabs displays. Invokes DataChanged for subclasses to - // update themselves appropriately. - void SetData(const TabRendererData& data); - const TabRendererData& data() const { return data_; } - - // Sets the network state. If the network state changes NetworkStateChanged is - // invoked. - virtual void UpdateLoadingAnimation(TabRendererData::NetworkState state); - - // Starts/Stops a pulse animation. - void StartPulse(); - void StopPulse(); - - // Used to set/check whether this Tab is being animated closed. - void set_closing(bool closing) { closing_ = closing; } - bool closing() const { return closing_; } - - // See description above field. - void set_dragging(bool dragging) { dragging_ = dragging; } - bool dragging() const { return dragging_; } - - // Sets the container all animations run from. - void set_animation_container(AnimationContainer* container) { - animation_container_ = container; - } - AnimationContainer* animation_container() const { - return animation_container_.get(); - } - - // Set the theme provider - because we get detached, we are frequently - // outside of a hierarchy with a theme provider at the top. This should be - // called whenever we're detached or attached to a hierarchy. - void set_theme_provider(ThemeProvider* provider) { - theme_provider_ = provider; - } - - // Returns true if the tab is selected. - virtual bool IsSelected() const; - - // Returns true if the tab is closeable. - bool IsCloseable() const; - - // views::View overrides: - virtual void OnMouseEntered(const views::MouseEvent& event); - virtual void OnMouseExited(const views::MouseEvent& event); - virtual bool OnMousePressed(const views::MouseEvent& event); - virtual bool OnMouseDragged(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, - bool canceled); - virtual bool GetTooltipText(const gfx::Point& p, std::wstring* tooltip); - virtual AccessibilityTypes::Role GetAccessibleRole(); - virtual ThemeProvider* GetThemeProvider(); - - protected: - // Invoked from SetData after |data_| has been updated to the new data. - virtual void DataChanged(const TabRendererData& old) {} - - // Invoked if data_.network_state changes, or the network_state is not none. - virtual void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, - TabRendererData::NetworkState state); - - TabController* controller() const { return controller_; } - - // Returns the pulse animation. The pulse animation is non-null if StartPulse - // has been invoked. - ThrobAnimation* pulse_animation() const { return pulse_animation_.get(); } - - // Returns the hover animation. This may return null. - const SlideAnimation* hover_animation() const { - return hover_animation_.get(); - } - - views::ImageButton* close_button() const { return close_button_; } - - // Paints the icon at the specified coordinates, mirrored for RTL if needed. - void PaintIcon(gfx::Canvas* canvas, int x, int y); - void PaintTitle(gfx::Canvas* canvas, SkColor title_color); - - // Overridden from AnimationDelegate: - virtual void AnimationProgressed(const Animation* animation); - virtual void AnimationCanceled(const Animation* animation); - virtual void AnimationEnded(const Animation* animation); - - // views::ButtonListener overrides: - virtual void ButtonPressed(views::Button* sender, - const views::Event& event); - - // views::ContextMenuController overrides: - virtual void ShowContextMenu(views::View* source, - const gfx::Point& p, - bool is_mouse_gesture); - - // Returns the bounds of the title. - virtual const gfx::Rect& title_bounds() const = 0; - - static gfx::Font* font() { return font_; } - static int font_height() { return font_height_; } - - private: - // The animation object used to swap the favicon with the sad tab icon. - class FavIconCrashAnimation; - - // Set the temporary offset for the favicon. This is used during the crash - // animation. - void SetFavIconHidingOffset(int offset); - - void DisplayCrashedFavIcon(); - void ResetCrashedFavIcon(); - - // Starts/Stops the crash animation. - void StartCrashAnimation(); - void StopCrashAnimation(); - - // Return true if the crash animation is currently running. - bool IsPerformingCrashAnimation() const; - - static void InitResources(); - - // The controller. - // WARNING: this is null during detached tab dragging. - TabController* controller_; - - TabRendererData data_; - - // True if the tab is being animated closed. - bool closing_; - - // True if the tab is being dragged. - bool dragging_; - - // Pulse animation. - scoped_ptr<ThrobAnimation> pulse_animation_; - - // Hover animation. - scoped_ptr<SlideAnimation> hover_animation_; - - // Crash animation. - scoped_ptr<FavIconCrashAnimation> crash_animation_; - - scoped_refptr<AnimationContainer> animation_container_; - - views::ImageButton* close_button_; - - // The current index of the loading animation. - int loading_animation_frame_; - - // Whether to disable throbber animations. Only true if this is an app tab - // renderer and a command line flag has been passed in to disable the - // animations. - bool throbber_disabled_; - - ThemeProvider* theme_provider_; - - // The offset used to animate the favicon location. This is used when the tab - // crashes. - int fav_icon_hiding_offset_; - - bool should_display_crashed_favicon_; - - static gfx::Font* font_; - static int font_height_; - - DISALLOW_COPY_AND_ASSIGN(BaseTab); -}; +#include "chrome/browser/ui/views/tabs/base_tab.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_H_ + diff --git a/chrome/browser/views/tabs/base_tab_strip.cc b/chrome/browser/views/tabs/base_tab_strip.cc deleted file mode 100644 index 4f844ed..0000000 --- a/chrome/browser/views/tabs/base_tab_strip.cc +++ /dev/null @@ -1,473 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/base_tab_strip.h" - -#include "base/logging.h" -#include "chrome/browser/view_ids.h" -#include "chrome/browser/views/tabs/dragged_tab_controller.h" -#include "chrome/browser/views/tabs/tab_strip_controller.h" -#include "views/widget/root_view.h" -#include "views/window/window.h" - -#if defined(OS_WIN) -#include "app/win_util.h" -#include "views/widget/widget_win.h" -#endif - -namespace { - -// Animation delegate used when a dragged tab is released. When done sets the -// dragging state to false. -class ResetDraggingStateDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { - public: - explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { - } - - virtual void AnimationEnded(const Animation* animation) { - tab_->set_dragging(false); - } - - virtual void AnimationCanceled(const Animation* animation) { - tab_->set_dragging(false); - } - - private: - BaseTab* tab_; - - DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); -}; - -} // namespace - -// AnimationDelegate used when removing a tab. Does the necessary cleanup when -// done. -class BaseTabStrip::RemoveTabDelegate - : public views::BoundsAnimator::OwnedAnimationDelegate { - public: - RemoveTabDelegate(BaseTabStrip* tab_strip, BaseTab* tab) - : tabstrip_(tab_strip), - tab_(tab) { - } - - virtual void AnimationEnded(const Animation* animation) { - CompleteRemove(); - } - - virtual void AnimationCanceled(const Animation* animation) { - // We can be canceled for two interesting reasons: - // . The tab we reference was dragged back into the tab strip. In this case - // we don't want to remove the tab (closing is false). - // . The drag was completed before the animation completed - // (DestroyDraggedSourceTab). In this case we need to remove the tab - // (closing is true). - if (tab_->closing()) - CompleteRemove(); - } - - private: - void CompleteRemove() { - if (!tab_->closing()) { - // The tab was added back yet we weren't canceled. This shouldn't happen. - NOTREACHED(); - return; - } - tabstrip_->RemoveAndDeleteTab(tab_); - HighlightCloseButton(); - } - - // When the animation completes, we send the Container a message to simulate - // a mouse moved event at the current mouse position. This tickles the Tab - // the mouse is currently over to show the "hot" state of the close button. - void HighlightCloseButton() { - if (tabstrip_->IsDragSessionActive() || - !tabstrip_->ShouldHighlightCloseButtonAfterRemove()) { - // This function is not required (and indeed may crash!) for removes - // spawned by non-mouse closes and drag-detaches. - return; - } - -#if defined(OS_WIN) - views::Widget* widget = tabstrip_->GetWidget(); - // This can be null during shutdown. See http://crbug.com/42737. - if (!widget) - return; - // Force the close button (that slides under the mouse) to highlight by - // saying the mouse just moved, but sending the same coordinates. - DWORD pos = GetMessagePos(); - POINT cursor_point = {GET_X_LPARAM(pos), GET_Y_LPARAM(pos)}; - MapWindowPoints(NULL, widget->GetNativeView(), &cursor_point, 1); - - static_cast<views::WidgetWin*>(widget)->ResetLastMouseMoveFlag(); - // Return to message loop - otherwise we may disrupt some operation that's - // in progress. - SendMessage(widget->GetNativeView(), WM_MOUSEMOVE, 0, - MAKELPARAM(cursor_point.x, cursor_point.y)); -#else - NOTIMPLEMENTED(); -#endif - } - - BaseTabStrip* tabstrip_; - BaseTab* tab_; - - DISALLOW_COPY_AND_ASSIGN(RemoveTabDelegate); -}; - -BaseTabStrip::BaseTabStrip(TabStripController* controller, Type type) - : controller_(controller), - type_(type), - attaching_dragged_tab_(false), - ALLOW_THIS_IN_INITIALIZER_LIST(bounds_animator_(this)) { -} - -BaseTabStrip::~BaseTabStrip() { -} - -void BaseTabStrip::UpdateLoadingAnimations() { - controller_->UpdateLoadingAnimations(); -} - -bool BaseTabStrip::IsAnimating() const { - return bounds_animator_.IsAnimating(); -} - -BaseTab* BaseTabStrip::GetSelectedBaseTab() const { - return GetBaseTabAtModelIndex(controller_->GetSelectedIndex()); -} - -void BaseTabStrip::AddTabAt(int model_index, - bool foreground, - const TabRendererData& data) { - BaseTab* tab = CreateTab(); - tab->SetData(data); - - TabData d = { tab, gfx::Rect() }; - tab_data_.insert(tab_data_.begin() + ModelIndexToTabIndex(model_index), d); - - AddChildView(tab); - - // Don't animate the first tab, it looks weird, and don't animate anything - // if the containing window isn't visible yet. - if (tab_count() > 1 && GetWindow() && GetWindow()->IsVisible()) - StartInsertTabAnimation(model_index, foreground); - else - DoLayout(); -} - -void BaseTabStrip::MoveTab(int from_model_index, int to_model_index) { - int from_tab_data_index = ModelIndexToTabIndex(from_model_index); - - BaseTab* tab = tab_data_[from_tab_data_index].tab; - tab_data_.erase(tab_data_.begin() + from_tab_data_index); - - TabData data = {tab, gfx::Rect()}; - - int to_tab_data_index = ModelIndexToTabIndex(to_model_index); - - tab_data_.insert(tab_data_.begin() + to_tab_data_index, data); - - StartMoveTabAnimation(); -} - -void BaseTabStrip::SetTabData(int model_index, const TabRendererData& data) { - BaseTab* tab = GetBaseTabAtModelIndex(model_index); - bool mini_state_changed = tab->data().mini != data.mini; - tab->SetData(data); - tab->SchedulePaint(); - - if (mini_state_changed) { - if (GetWindow() && GetWindow()->IsVisible()) - StartMiniTabAnimation(); - else - DoLayout(); - } -} - -BaseTab* BaseTabStrip::GetBaseTabAtModelIndex(int model_index) const { - return base_tab_at_tab_index(ModelIndexToTabIndex(model_index)); -} - -int BaseTabStrip::GetModelIndexOfBaseTab(const BaseTab* tab) const { - for (int i = 0, model_index = 0; i < tab_count(); ++i) { - BaseTab* current_tab = base_tab_at_tab_index(i); - if (!current_tab->closing()) { - if (current_tab == tab) - return model_index; - model_index++; - } - } - return -1; -} - -int BaseTabStrip::GetModelCount() const { - return controller_->GetCount(); -} - -bool BaseTabStrip::IsValidModelIndex(int model_index) const { - return controller_->IsValidIndex(model_index); -} - -int BaseTabStrip::ModelIndexToTabIndex(int model_index) const { - int current_model_index = 0; - for (int i = 0; i < tab_count(); ++i) { - if (!base_tab_at_tab_index(i)->closing()) { - if (current_model_index == model_index) - return i; - current_model_index++; - } - } - return static_cast<int>(tab_data_.size()); -} - -bool BaseTabStrip::IsDragSessionActive() const { - return drag_controller_.get() != NULL; -} - -void BaseTabStrip::SelectTab(BaseTab* tab) { - int model_index = GetModelIndexOfBaseTab(tab); - if (IsValidModelIndex(model_index)) - controller_->SelectTab(model_index); -} - -void BaseTabStrip::CloseTab(BaseTab* tab) { - // Find the closest model index. We do this so that the user can rapdily close - // tabs and have the close click close the next tab. - int model_index = 0; - for (int i = 0; i < tab_count(); ++i) { - BaseTab* current_tab = base_tab_at_tab_index(i); - if (current_tab == tab) - break; - if (!current_tab->closing()) - model_index++; - } - - if (IsValidModelIndex(model_index)) - controller_->CloseTab(model_index); -} - -void BaseTabStrip::ShowContextMenu(BaseTab* tab, const gfx::Point& p) { - controller_->ShowContextMenu(tab, p); -} - -bool BaseTabStrip::IsTabSelected(const BaseTab* tab) const { - int model_index = GetModelIndexOfBaseTab(tab); - return IsValidModelIndex(model_index) && - controller_->IsTabSelected(model_index); -} - -bool BaseTabStrip::IsTabPinned(const BaseTab* tab) const { - if (tab->closing()) - return false; - - int model_index = GetModelIndexOfBaseTab(tab); - return IsValidModelIndex(model_index) && - controller_->IsTabPinned(model_index); -} - -bool BaseTabStrip::IsTabCloseable(const BaseTab* tab) const { - int model_index = GetModelIndexOfBaseTab(tab); - return !IsValidModelIndex(model_index) || - controller_->IsTabCloseable(model_index); -} - -void BaseTabStrip::MaybeStartDrag(BaseTab* tab, - const views::MouseEvent& event) { - // Don't accidentally start any drag operations during animations if the - // mouse is down... during an animation tabs are being resized automatically, - // so the View system can misinterpret this easily if the mouse is down that - // the user is dragging. - if (IsAnimating() || tab->closing() || - controller_->HasAvailableDragActions() == 0) { - return; - } - int model_index = GetModelIndexOfBaseTab(tab); - if (!IsValidModelIndex(model_index)) { - CHECK(false); - return; - } - drag_controller_.reset(new DraggedTabController(tab, this)); - drag_controller_->CaptureDragInfo(tab, event.location()); -} - -void BaseTabStrip::ContinueDrag(const views::MouseEvent& event) { - // We can get called even if |MaybeStartDrag| wasn't called in the event of - // a TabStrip animation when the mouse button is down. In this case we should - // _not_ continue the drag because it can lead to weird bugs. - if (drag_controller_.get()) { - bool started_drag = drag_controller_->started_drag(); - drag_controller_->Drag(); - if (drag_controller_->started_drag() && !started_drag) { - // The drag just started. Redirect mouse events to us to that the tab that - // originated the drag can be safely deleted. - GetRootView()->SetMouseHandler(this); - } - } -} - -bool BaseTabStrip::EndDrag(bool canceled) { - if (!drag_controller_.get()) - return false; - bool started_drag = drag_controller_->started_drag(); - drag_controller_->EndDrag(canceled); - return started_drag; -} - -BaseTab* BaseTabStrip::GetTabAt(BaseTab* tab, - const gfx::Point& tab_in_tab_coordinates) { - gfx::Point local_point = tab_in_tab_coordinates; - ConvertPointToView(tab, this, &local_point); - views::View* view = GetViewForPoint(local_point); - if (!view) - return NULL; // No tab contains the point. - - // Walk up the view hierarchy until we find a tab, or the TabStrip. - while (view && view != this && view->GetID() != VIEW_ID_TAB) - view = view->GetParent(); - - return view && view->GetID() == VIEW_ID_TAB ? - static_cast<BaseTab*>(view) : NULL; -} - -void BaseTabStrip::Layout() { - // Only do a layout if our size changed. - if (last_layout_size_ == size()) - return; - DoLayout(); -} - -bool BaseTabStrip::OnMouseDragged(const views::MouseEvent& event) { - if (drag_controller_.get()) - drag_controller_->Drag(); - return true; -} - -void BaseTabStrip::OnMouseReleased(const views::MouseEvent& event, - bool canceled) { - EndDrag(canceled); -} - -void BaseTabStrip::StartRemoveTabAnimation(int model_index) { - PrepareForAnimation(); - - // Mark the tab as closing. - BaseTab* tab = GetBaseTabAtModelIndex(model_index); - tab->set_closing(true); - - // Start an animation for the tabs. - GenerateIdealBounds(); - AnimateToIdealBounds(); - - // Animate the tab being closed to 0x0. - gfx::Rect tab_bounds = tab->bounds(); - if (type() == HORIZONTAL_TAB_STRIP) - tab_bounds.set_width(0); - else - tab_bounds.set_height(0); - bounds_animator_.AnimateViewTo(tab, tab_bounds); - - // Register delegate to do cleanup when done, BoundsAnimator takes - // ownership of RemoveTabDelegate. - bounds_animator_.SetAnimationDelegate(tab, new RemoveTabDelegate(this, tab), - true); -} - -void BaseTabStrip::StartMiniTabAnimation() { - PrepareForAnimation(); - - GenerateIdealBounds(); - AnimateToIdealBounds(); -} - -void BaseTabStrip::RemoveAndDeleteTab(BaseTab* tab) { - int tab_data_index = TabIndexOfTab(tab); - - DCHECK(tab_data_index != -1); - - // Remove the Tab from the TabStrip's list... - tab_data_.erase(tab_data_.begin() + tab_data_index); - - delete tab; -} - -int BaseTabStrip::TabIndexOfTab(BaseTab* tab) const { - for (int i = 0; i < tab_count(); ++i) { - if (base_tab_at_tab_index(i) == tab) - return i; - } - return -1; -} - -void BaseTabStrip::DestroyDragController() { - if (IsDragSessionActive()) - drag_controller_.reset(NULL); -} - -void BaseTabStrip::StartedDraggingTab(BaseTab* tab) { - PrepareForAnimation(); - - // Reset the dragging state of all other tabs. We do this as the painting code - // only handles one tab being dragged at a time. If another tab is marked as - // dragging, it should also be closing. - for (int i = 0; i < tab_count(); ++i) - base_tab_at_tab_index(i)->set_dragging(false); - - tab->set_dragging(true); - - // Stop any animations on the tab. - bounds_animator_.StopAnimatingView(tab); - - // Move the tab to its ideal bounds. - GenerateIdealBounds(); - int tab_data_index = TabIndexOfTab(tab); - DCHECK(tab_data_index != -1); - tab->SetBounds(ideal_bounds(tab_data_index)); - SchedulePaint(); -} - -void BaseTabStrip::StoppedDraggingTab(BaseTab* tab) { - int tab_data_index = TabIndexOfTab(tab); - if (tab_data_index == -1) { - // The tab was removed before the drag completed. Don't do anything. - return; - } - - PrepareForAnimation(); - - // Animate the view back to its correct position. - GenerateIdealBounds(); - AnimateToIdealBounds(); - bounds_animator_.AnimateViewTo(tab, ideal_bounds(TabIndexOfTab(tab))); - - // Install a delegate to reset the dragging state when done. We have to leave - // dragging true for the tab otherwise it'll draw beneath the new tab button. - bounds_animator_.SetAnimationDelegate(tab, - new ResetDraggingStateDelegate(tab), - true); -} - -void BaseTabStrip::PrepareForAnimation() { - if (!IsDragSessionActive() && !DraggedTabController::IsAttachedTo(this)) { - for (int i = 0; i < tab_count(); ++i) - base_tab_at_tab_index(i)->set_dragging(false); - } -} - -AnimationDelegate* BaseTabStrip::CreateRemoveTabDelegate(BaseTab* tab) { - return new RemoveTabDelegate(this, tab); -} - -void BaseTabStrip::DoLayout() { - last_layout_size_ = size(); - - StopAnimating(false); - - GenerateIdealBounds(); - - for (int i = 0; i < tab_count(); ++i) - tab_data_[i].tab->SetBounds(tab_data_[i].ideal_bounds); - - SchedulePaint(); -} diff --git a/chrome/browser/views/tabs/base_tab_strip.h b/chrome/browser/views/tabs/base_tab_strip.h index e3f5231..603dcf9 100644 --- a/chrome/browser/views/tabs/base_tab_strip.h +++ b/chrome/browser/views/tabs/base_tab_strip.h @@ -6,261 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_ #pragma once -#include <vector> - -#include "base/scoped_ptr.h" -#include "chrome/browser/views/tabs/base_tab.h" -#include "chrome/browser/views/tabs/tab_controller.h" -#include "views/animation/bounds_animator.h" -#include "views/view.h" - -class BaseTab; -class DraggedTabController; -class TabStrip; -class TabStripController; -class ThemeProvider; - -// Base class for the view tab strip implementations. -class BaseTabStrip : public views::View, - public TabController { - public: - enum Type { - HORIZONTAL_TAB_STRIP, - VERTICAL_TAB_STRIP - }; - - BaseTabStrip(TabStripController* controller, Type type); - virtual ~BaseTabStrip(); - - Type type() const { return type_; } - - // Returns the preferred height of this TabStrip. This is based on the - // typical height of its constituent tabs. - virtual int GetPreferredHeight() = 0; - - // Set the background offset used by inactive tabs to match the frame image. - virtual void SetBackgroundOffset(const gfx::Point& offset) = 0; - - // Returns true if the specified point(TabStrip coordinates) is - // in the window caption area of the browser window. - virtual bool IsPositionInWindowCaption(const gfx::Point& point) = 0; - - // Sets the bounds of the tab at the specified |tab_index|. |tab_bounds| are - // in TabStrip coordinates. - virtual void SetDraggedTabBounds(int tab_index, - const gfx::Rect& tab_bounds) = 0; - - // Updates the loading animations displayed by tabs in the tabstrip to the - // next frame. - void UpdateLoadingAnimations(); - - // Returns true if Tabs in this TabStrip are currently changing size or - // position. - virtual bool IsAnimating() const; - - // Returns this object as a TabStrip if it is one. - virtual TabStrip* AsTabStrip() = 0; - - // Starts highlighting the tab at the specified index. - virtual void StartHighlight(int model_index) = 0; - - // Stops all tab higlighting. - virtual void StopAllHighlighting() = 0; - - // Returns the selected tab. - virtual BaseTab* GetSelectedBaseTab() const; - - // Retrieves the ideal bounds for the Tab at the specified index. - const gfx::Rect& ideal_bounds(int tab_data_index) { - return tab_data_[tab_data_index].ideal_bounds; - } - - // Creates and returns a tab that can be used for dragging. Ownership passes - // to the caller. - virtual BaseTab* CreateTabForDragging() = 0; - - // Adds a tab at the specified index. - void AddTabAt(int model_index, - bool foreground, - const TabRendererData& data); - - // Invoked from the controller when the close initiates from the TabController - // (the user clicked the tab close button or middle clicked the tab). This is - // invoked from Close. Because of unload handlers Close is not always - // immediately followed by RemoveTabAt. - virtual void PrepareForCloseAt(int model_index) {} - - // Removes a tab at the specified index. - virtual void RemoveTabAt(int model_index) = 0; - - // Selects a tab at the specified index. |old_model_index| is the selected - // index prior to the selection change. - virtual void SelectTabAt(int old_model_index, int new_model_index) = 0; - - // Moves a tab. - virtual void MoveTab(int from_model_index, int to_model_index); - - // Invoked when the title of a tab changes and the tab isn't loading. - virtual void TabTitleChangedNotLoading(int model_index) = 0; - - // Sets the tab data at the specified model index. - virtual void SetTabData(int model_index, const TabRendererData& data); - - // Returns the tab at the specified model index. - virtual BaseTab* GetBaseTabAtModelIndex(int model_index) const; - - // Returns the tab at the specified tab index. - BaseTab* base_tab_at_tab_index(int tab_index) const { - return tab_data_[tab_index].tab; - } - - // Returns the index of the specified tab in the model coordiate system, or - // -1 if tab is closing or not valid. - virtual int GetModelIndexOfBaseTab(const BaseTab* tab) const; - - // Gets the number of Tabs in the tab strip. - // WARNING: this is the number of tabs displayed by the tabstrip, which if - // an animation is ongoing is not necessarily the same as the number of tabs - // in the model. - int tab_count() const { return static_cast<int>(tab_data_.size()); } - - // Cover method for TabStripController::GetCount. - int GetModelCount() const; - - // Cover method for TabStripController::IsValidIndex. - bool IsValidModelIndex(int model_index) const; - - // Returns the index into |tab_data_| corresponding to the index from the - // TabStripModel, or |tab_data_.size()| if there is no tab representing - // |model_index|. - int ModelIndexToTabIndex(int model_index) const; - - TabStripController* controller() const { return controller_.get(); } - - // Returns true if a drag session is currently active. - bool IsDragSessionActive() const; - - // TabController overrides: - virtual void SelectTab(BaseTab* tab); - virtual void CloseTab(BaseTab* tab); - virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p); - virtual bool IsTabSelected(const BaseTab* tab) const; - virtual bool IsTabPinned(const BaseTab* tab) const; - virtual bool IsTabCloseable(const BaseTab* tab) const; - virtual void MaybeStartDrag(BaseTab* tab, - const views::MouseEvent& event); - virtual void ContinueDrag(const views::MouseEvent& event); - virtual bool EndDrag(bool canceled); - virtual BaseTab* GetTabAt(BaseTab* tab, - const gfx::Point& tab_in_tab_coordinates); - - // View overrides: - virtual void Layout(); - - protected: - // The Tabs we contain, and their last generated "good" bounds. - struct TabData { - BaseTab* tab; - gfx::Rect ideal_bounds; - }; - - // View overrides. - virtual bool OnMouseDragged(const views::MouseEvent& event); - virtual void OnMouseReleased(const views::MouseEvent& event, - bool canceled); - - // Creates and returns a new tab. The caller owners the returned tab. - virtual BaseTab* CreateTab() = 0; - - // Invoked from |AddTabAt| after the newly created tab has been inserted. - // Subclasses should either start an animation, or layout. - virtual void StartInsertTabAnimation(int model_index, bool foreground) = 0; - - // Invoked from |MoveTab| after |tab_data_| has been updated to animate the - // move. - virtual void StartMoveTabAnimation() = 0; - - // Starts the remove tab animation. - virtual void StartRemoveTabAnimation(int model_index); - - // Starts the mini-tab animation. - virtual void StartMiniTabAnimation(); - - // Returns whether the highlight button should be highlighted after a remove. - virtual bool ShouldHighlightCloseButtonAfterRemove() { return true; } - - // Animates all the views to their ideal bounds. - // NOTE: this does *not* invoke GenerateIdealBounds, it uses the bounds - // currently set in ideal_bounds. - virtual void AnimateToIdealBounds() = 0; - - // Cleans up the Tab from the TabStrip. This is called from the tab animation - // code and is not a general-purpose method. - void RemoveAndDeleteTab(BaseTab* tab); - - // Resets the bounds of all non-closing tabs. - virtual void GenerateIdealBounds() = 0; - - void set_ideal_bounds(int index, const gfx::Rect& bounds) { - tab_data_[index].ideal_bounds = bounds; - } - - // Returns the index into |tab_data_| corresponding to the specified tab, or - // -1 if the tab isn't in |tab_data_|. - int TabIndexOfTab(BaseTab* tab) const; - - // Stops any ongoing animations. If |layout| is true and an animation is - // ongoing this does a layout. - virtual void StopAnimating(bool layout) = 0; - - // Destroys the active drag controller. - void DestroyDragController(); - - // Used by DraggedTabController when the user starts or stops dragging a tab. - void StartedDraggingTab(BaseTab* tab); - void StoppedDraggingTab(BaseTab* tab); - - // See description above field for details. - bool attaching_dragged_tab() const { return attaching_dragged_tab_; } - - views::BoundsAnimator& bounds_animator() { return bounds_animator_; } - - // Invoked prior to starting a new animation. - virtual void PrepareForAnimation(); - - // Creates an AnimationDelegate that resets state after a remove animation - // completes. The caller owns the returned object. - AnimationDelegate* CreateRemoveTabDelegate(BaseTab* tab); - - // Invoked from Layout if the size changes or layout is really needed. - virtual void DoLayout(); - - private: - class RemoveTabDelegate; - - friend class DraggedTabController; - - // See description above field for details. - void set_attaching_dragged_tab(bool value) { attaching_dragged_tab_ = value; } - - scoped_ptr<TabStripController> controller_; - - const Type type_; - - std::vector<TabData> tab_data_; - - // The controller for a drag initiated from a Tab. Valid for the lifetime of - // the drag session. - scoped_ptr<DraggedTabController> drag_controller_; - - // If true, the insert is a result of a drag attaching the tab back to the - // model. - bool attaching_dragged_tab_; - - views::BoundsAnimator bounds_animator_; - - // Size we last layed out at. - gfx::Size last_layout_size_; -}; +#include "chrome/browser/ui/views/tabs/base_tab_strip.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_BASE_TAB_STRIP_H_ + diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/views/tabs/browser_tab_strip_controller.cc deleted file mode 100644 index 78b1aa1..0000000 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.cc +++ /dev/null @@ -1,428 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/browser_tab_strip_controller.h" - -#include "base/auto_reset.h" -#include "base/command_line.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tab_menu_model.h" -#include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/views/tabs/base_tab_strip.h" -#include "chrome/browser/views/tabs/tab_renderer_data.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/url_constants.h" -#include "views/controls/menu/menu_2.h" -#include "views/widget/widget.h" - -static TabRendererData::NetworkState TabContentsNetworkState( - TabContents* contents) { - if (!contents || !contents->is_loading()) - return TabRendererData::NETWORK_STATE_NONE; - if (contents->waiting_for_response()) - return TabRendererData::NETWORK_STATE_WAITING; - return TabRendererData::NETWORK_STATE_LOADING; -} - -class BrowserTabStripController::TabContextMenuContents - : public menus::SimpleMenuModel::Delegate { - public: - TabContextMenuContents(BaseTab* tab, - BrowserTabStripController* controller) - : ALLOW_THIS_IN_INITIALIZER_LIST( - model_(this, controller->IsTabPinned(tab))), - tab_(tab), - controller_(controller), - last_command_(TabStripModel::CommandFirst) { - Build(); - } - virtual ~TabContextMenuContents() { - menu_->CancelMenu(); - if (controller_) - controller_->tabstrip_->StopAllHighlighting(); - } - - void Cancel() { - controller_ = NULL; - } - - void RunMenuAt(const gfx::Point& point) { - BrowserTabStripController* controller = controller_; - menu_->RunMenuAt(point, views::Menu2::ALIGN_TOPLEFT); - // We could be gone now. Assume |this| is junk! - if (controller) - controller->tabstrip_->StopAllHighlighting(); - } - - // Overridden from menus::SimpleMenuModel::Delegate: - virtual bool IsCommandIdChecked(int command_id) const { - return controller_->IsCommandCheckedForTab( - static_cast<TabStripModel::ContextMenuCommand>(command_id), - tab_); - } - virtual bool IsCommandIdEnabled(int command_id) const { - return controller_->IsCommandEnabledForTab( - static_cast<TabStripModel::ContextMenuCommand>(command_id), - tab_); - } - virtual bool GetAcceleratorForCommandId( - int command_id, - menus::Accelerator* accelerator) { - return controller_->tabstrip_->GetWidget()->GetAccelerator(command_id, - accelerator); - } - virtual void CommandIdHighlighted(int command_id) { - controller_->StopHighlightTabsForCommand(last_command_, tab_); - last_command_ = static_cast<TabStripModel::ContextMenuCommand>(command_id); - controller_->StartHighlightTabsForCommand(last_command_, tab_); - } - virtual void ExecuteCommand(int command_id) { - controller_->ExecuteCommandForTab( - static_cast<TabStripModel::ContextMenuCommand>(command_id), - tab_); - } - - private: - void Build() { - menu_.reset(new views::Menu2(&model_)); - } - - TabMenuModel model_; - scoped_ptr<views::Menu2> menu_; - - // The tab we're showing a menu for. - BaseTab* tab_; - - // A pointer back to our hosting controller, for command state information. - BrowserTabStripController* controller_; - - // The last command that was selected, so that we can start/stop highlighting - // appropriately as the user moves through the menu. - TabStripModel::ContextMenuCommand last_command_; - - DISALLOW_COPY_AND_ASSIGN(TabContextMenuContents); -}; - -//////////////////////////////////////////////////////////////////////////////// -// BrowserTabStripController, public: - -BrowserTabStripController::BrowserTabStripController(Browser* browser, - TabStripModel* model) - : model_(model), - tabstrip_(NULL), - browser_(browser) { - model_->AddObserver(this); - - notification_registrar_.Add(this, - NotificationType::TAB_CLOSEABLE_STATE_CHANGED, - NotificationService::AllSources()); -} - -BrowserTabStripController::~BrowserTabStripController() { - // When we get here the TabStrip is being deleted. We need to explicitly - // cancel the menu, otherwise it may try to invoke something on the tabstrip - // from it's destructor. - if (context_menu_contents_.get()) - context_menu_contents_->Cancel(); - - model_->RemoveObserver(this); -} - -void BrowserTabStripController::InitFromModel(BaseTabStrip* tabstrip) { - tabstrip_ = tabstrip; - // Walk the model, calling our insertion observer method for each item within - // it. - for (int i = 0; i < model_->count(); ++i) { - TabInsertedAt(model_->GetTabContentsAt(i), i, - i == model_->selected_index()); - } -} - -bool BrowserTabStripController::IsCommandEnabledForTab( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) const { - int model_index = tabstrip_->GetModelIndexOfBaseTab(tab); - return model_->ContainsIndex(model_index) ? - model_->IsContextMenuCommandEnabled(model_index, command_id) : false; -} - -bool BrowserTabStripController::IsCommandCheckedForTab( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) const { - int model_index = tabstrip_->GetModelIndexOfBaseTab(tab); - return model_->ContainsIndex(model_index) ? - model_->IsContextMenuCommandChecked(model_index, command_id) : false; -} - -void BrowserTabStripController::ExecuteCommandForTab( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) { - int model_index = tabstrip_->GetModelIndexOfBaseTab(tab); - if (model_->ContainsIndex(model_index)) - model_->ExecuteContextMenuCommand(model_index, command_id); -} - -bool BrowserTabStripController::IsTabPinned(BaseTab* tab) { - return IsTabPinned(tabstrip_->GetModelIndexOfBaseTab(tab)); -} - -int BrowserTabStripController::GetCount() const { - return model_->count(); -} - -bool BrowserTabStripController::IsValidIndex(int index) const { - return model_->ContainsIndex(index); -} - -int BrowserTabStripController::GetSelectedIndex() const { - return model_->selected_index(); -} - -bool BrowserTabStripController::IsTabSelected(int model_index) const { - return model_->selected_index() == model_index; -} - -bool BrowserTabStripController::IsTabPinned(int model_index) const { - return model_->ContainsIndex(model_index) && model_->IsTabPinned(model_index); -} - -bool BrowserTabStripController::IsTabCloseable(int model_index) const { - return !model_->ContainsIndex(model_index) || - model_->delegate()->CanCloseTab(); -} - -bool BrowserTabStripController::IsNewTabPage(int model_index) const { - return model_->ContainsIndex(model_index) && - model_->GetTabContentsAt(model_index)->GetURL() == - GURL(chrome::kChromeUINewTabURL); -} - -void BrowserTabStripController::SelectTab(int model_index) { - model_->SelectTabContentsAt(model_index, true); -} - -void BrowserTabStripController::CloseTab(int model_index) { - tabstrip_->PrepareForCloseAt(model_index); - model_->CloseTabContentsAt(model_index, - TabStripModel::CLOSE_USER_GESTURE | - TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); -} - -void BrowserTabStripController::ShowContextMenu(BaseTab* tab, - const gfx::Point& p) { - context_menu_contents_.reset(new TabContextMenuContents(tab, this)); - context_menu_contents_->RunMenuAt(p); -} - -void BrowserTabStripController::UpdateLoadingAnimations() { - // Don't use the model count here as it's possible for this to be invoked - // before we've applied an update from the model (Browser::TabInsertedAt may - // be processed before us and invokes this). - for (int tab_index = 0, tab_count = tabstrip_->tab_count(); - tab_index < tab_count; ++tab_index) { - BaseTab* tab = tabstrip_->base_tab_at_tab_index(tab_index); - int model_index = tabstrip_->GetModelIndexOfBaseTab(tab); - if (model_->ContainsIndex(model_index)) { - TabContents* contents = model_->GetTabContentsAt(model_index); - tab->UpdateLoadingAnimation(TabContentsNetworkState(contents)); - } - } -} - -int BrowserTabStripController::HasAvailableDragActions() const { - return model_->delegate()->GetDragActions(); -} - -void BrowserTabStripController::PerformDrop(bool drop_before, - int index, - const GURL& url) { - if (drop_before) { - UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLBetweenTabs"), - model_->profile()); - - // Insert a new tab. - TabContents* contents = model_->delegate()->CreateTabContentsForURL( - url, GURL(), model_->profile(), PageTransition::TYPED, false, NULL); - model_->AddTabContents(contents, index, PageTransition::GENERATED, - TabStripModel::ADD_SELECTED); - } else { - UserMetrics::RecordAction(UserMetricsAction("Tab_DropURLOnTab"), - model_->profile()); - - model_->GetTabContentsAt(index)->controller().LoadURL( - url, GURL(), PageTransition::GENERATED); - model_->SelectTabContentsAt(index, true); - } -} - -bool BrowserTabStripController::IsCompatibleWith(BaseTabStrip* other) const { - Profile* other_profile = - static_cast<BrowserTabStripController*>(other->controller())->profile(); - return other_profile == profile(); -} - -void BrowserTabStripController::CreateNewTab() { - UserMetrics::RecordAction(UserMetricsAction("NewTab_Button"), - model_->profile()); - - model_->delegate()->AddBlankTab(true); -} - -//////////////////////////////////////////////////////////////////////////////// -// BrowserTabStripController, TabStripModelObserver implementation: - -void BrowserTabStripController::TabInsertedAt(TabContents* contents, - int model_index, - bool foreground) { - DCHECK(contents); - DCHECK(model_index == TabStripModel::kNoTab || - model_->ContainsIndex(model_index)); - // This tab may be attached to another browser window, we should notify - // renderer. - contents->render_view_host()->UpdateBrowserWindowId( - contents->controller().window_id().id()); - - TabRendererData data; - SetTabRendererDataFromModel(contents, model_index, &data); - tabstrip_->AddTabAt(model_index, foreground, data); -} - -void BrowserTabStripController::TabDetachedAt(TabContents* contents, - int model_index) { - tabstrip_->RemoveTabAt(model_index); -} - -void BrowserTabStripController::TabSelectedAt(TabContents* old_contents, - TabContents* contents, - int model_index, - bool user_gesture) { - tabstrip_->SelectTabAt(model_->GetIndexOfTabContents(old_contents), - model_index); -} - -void BrowserTabStripController::TabMoved(TabContents* contents, - int from_model_index, - int to_model_index) { - // Update the data first as the pinned state may have changed. - TabRendererData data; - SetTabRendererDataFromModel(contents, to_model_index, &data); - tabstrip_->SetTabData(from_model_index, data); - - tabstrip_->MoveTab(from_model_index, to_model_index); -} - -void BrowserTabStripController::TabChangedAt(TabContents* contents, - int model_index, - TabChangeType change_type) { - if (change_type == TITLE_NOT_LOADING) { - tabstrip_->TabTitleChangedNotLoading(model_index); - // We'll receive another notification of the change asynchronously. - return; - } - - SetTabDataAt(contents, model_index); -} - -void BrowserTabStripController::TabReplacedAt(TabContents* old_contents, - TabContents* new_contents, - int model_index) { - SetTabDataAt(new_contents, model_index); -} - -void BrowserTabStripController::TabPinnedStateChanged(TabContents* contents, - int model_index) { - // Currently none of the renderers render pinned state differently. -} - -void BrowserTabStripController::TabMiniStateChanged( - TabContents* contents, - int model_index) { - SetTabDataAt(contents, model_index); -} - -void BrowserTabStripController::TabBlockedStateChanged(TabContents* contents, - int model_index) { - SetTabDataAt(contents, model_index); -} - -void BrowserTabStripController::SetTabDataAt(TabContents* contents, - int model_index) { - TabRendererData data; - SetTabRendererDataFromModel(contents, model_index, &data); - tabstrip_->SetTabData(model_index, data); -} - -void BrowserTabStripController::SetTabRendererDataFromModel( - TabContents* contents, - int model_index, - TabRendererData* data) { - SkBitmap* app_icon = NULL; - - // Extension App icons are slightly larger than favicons, so only allow - // them if permitted by the model. - if (model_->delegate()->LargeIconsPermitted()) - app_icon = contents->GetExtensionAppIcon(); - - if (app_icon) - data->favicon = *app_icon; - else - data->favicon = contents->GetFavIcon(); - data->network_state = TabContentsNetworkState(contents); - data->title = contents->GetTitle(); - data->loading = contents->is_loading(); - data->crashed = contents->is_crashed(); - data->off_the_record = contents->profile()->IsOffTheRecord(); - data->show_icon = contents->ShouldDisplayFavIcon(); - data->mini = model_->IsMiniTab(model_index); - data->blocked = model_->IsTabBlocked(model_index); - data->app = contents->is_app(); -} - -void BrowserTabStripController::StartHighlightTabsForCommand( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) { - if (command_id == TabStripModel::CommandCloseOtherTabs || - command_id == TabStripModel::CommandCloseTabsToRight) { - int model_index = tabstrip_->GetModelIndexOfBaseTab(tab); - if (IsValidIndex(model_index)) { - std::vector<int> indices = - model_->GetIndicesClosedByCommand(model_index, command_id); - for (std::vector<int>::const_iterator i = indices.begin(); - i != indices.end(); ++i) { - tabstrip_->StartHighlight(*i); - } - } - } -} - -void BrowserTabStripController::StopHighlightTabsForCommand( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) { - if (command_id == TabStripModel::CommandCloseTabsToRight || - command_id == TabStripModel::CommandCloseOtherTabs) { - // Just tell all Tabs to stop pulsing - it's safe. - tabstrip_->StopAllHighlighting(); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// BrowserTabStripController, NotificationObserver implementation: - -void BrowserTabStripController::Observe(NotificationType type, - const NotificationSource& source, const NotificationDetails& details) { - DCHECK(type.value == NotificationType::TAB_CLOSEABLE_STATE_CHANGED); - // Note that this notification may be fired during a model mutation and - // possibly before the tabstrip has processed the change. - // Here, we just re-layout each existing tab to reflect the change in its - // closeable state, and then schedule paint for entire tabstrip. - for (int i = 0; i < tabstrip_->tab_count(); ++i) { - tabstrip_->base_tab_at_tab_index(i)->Layout(); - } - tabstrip_->SchedulePaint(); -} diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h index bbf1121..6606f28 100644 --- a/chrome/browser/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/views/tabs/browser_tab_strip_controller.h @@ -6,116 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_ #pragma once -#include "base/scoped_ptr.h" -#include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/views/tabs/tab_strip_controller.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" - -class BaseTab; -class BaseTabStrip; -class Browser; - -struct TabRendererData; - -// An implementation of TabStripController that sources data from the -// TabContentses in a TabStripModel. -class BrowserTabStripController : public TabStripController, - public TabStripModelObserver, - public NotificationObserver { - public: - BrowserTabStripController(Browser* browser, TabStripModel* model); - virtual ~BrowserTabStripController(); - - void InitFromModel(BaseTabStrip* tabstrip); - - TabStripModel* model() const { return model_; } - - bool IsCommandEnabledForTab(TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) const; - bool IsCommandCheckedForTab(TabStripModel::ContextMenuCommand command_id, - BaseTab* tab) const; - void ExecuteCommandForTab(TabStripModel::ContextMenuCommand command_id, - BaseTab* tab); - bool IsTabPinned(BaseTab* tab); - - // TabStripController implementation: - virtual int GetCount() const; - virtual bool IsValidIndex(int model_index) const; - virtual int GetSelectedIndex() const; - virtual bool IsTabSelected(int model_index) const; - virtual bool IsTabPinned(int model_index) const; - virtual bool IsTabCloseable(int model_index) const; - virtual bool IsNewTabPage(int model_index) const; - virtual void SelectTab(int model_index); - virtual void CloseTab(int model_index); - virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p); - virtual void UpdateLoadingAnimations(); - virtual int HasAvailableDragActions() const; - virtual void PerformDrop(bool drop_before, int index, const GURL& url); - virtual bool IsCompatibleWith(BaseTabStrip* other) const; - virtual void CreateNewTab(); - - // TabStripModelObserver implementation: - virtual void TabInsertedAt(TabContents* contents, - int model_index, - bool foreground); - virtual void TabDetachedAt(TabContents* contents, int model_index); - virtual void TabSelectedAt(TabContents* old_contents, - TabContents* contents, - int model_index, - bool user_gesture); - virtual void TabMoved(TabContents* contents, - int from_model_index, - int to_model_index); - virtual void TabChangedAt(TabContents* contents, - int model_index, - TabChangeType change_type); - virtual void TabReplacedAt(TabContents* old_contents, - TabContents* new_contents, - int model_index); - virtual void TabPinnedStateChanged(TabContents* contents, int model_index); - virtual void TabMiniStateChanged(TabContents* contents, int model_index); - virtual void TabBlockedStateChanged(TabContents* contents, int model_index); - - // NotificationObserver implementation: - virtual void Observe(NotificationType type, const NotificationSource& source, - const NotificationDetails& details); - - private: - class TabContextMenuContents; - - // Invokes tabstrip_->SetTabData. - void SetTabDataAt(TabContents* contents, int model_index); - - // Sets the TabRendererData from the TabStripModel. - void SetTabRendererDataFromModel(TabContents* contents, - int model_index, - TabRendererData* data); - - void StartHighlightTabsForCommand( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab); - void StopHighlightTabsForCommand( - TabStripModel::ContextMenuCommand command_id, - BaseTab* tab); - - Profile* profile() const { return model_->profile(); } - - TabStripModel* model_; - - BaseTabStrip* tabstrip_; - - // Non-owning pointer to the browser which is using this controller. - Browser* browser_; - - // If non-NULL it means we're showing a menu for the tab. - scoped_ptr<TabContextMenuContents> context_menu_contents_; - - NotificationRegistrar notification_registrar_; - - DISALLOW_COPY_AND_ASSIGN(BrowserTabStripController); -}; +#include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_ diff --git a/chrome/browser/views/tabs/dragged_tab_controller.cc b/chrome/browser/views/tabs/dragged_tab_controller.cc deleted file mode 100644 index 3798180..0000000 --- a/chrome/browser/views/tabs/dragged_tab_controller.cc +++ /dev/null @@ -1,1341 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/dragged_tab_controller.h" - -#include <math.h> -#include <set> - -#include "app/animation.h" -#include "app/slide_animation.h" -#include "app/resource_bundle.h" -#include "base/callback.h" -#include "base/i18n/rtl.h" -#include "chrome/browser/browser_window.h" -#include "chrome/browser/extensions/extension_function_dispatcher.h" -#include "chrome/browser/tab_contents/tab_contents.h" -#include "chrome/browser/tabs/tab_strip_model.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/views/frame/browser_view.h" -#include "chrome/browser/views/tabs/base_tab.h" -#include "chrome/browser/views/tabs/base_tab_strip.h" -#include "chrome/browser/views/tabs/browser_tab_strip_controller.h" -#include "chrome/browser/views/tabs/dragged_tab_view.h" -#include "chrome/browser/views/tabs/native_view_photobooth.h" -#include "chrome/browser/views/tabs/side_tab.h" -#include "chrome/browser/views/tabs/side_tab_strip.h" -#include "chrome/browser/views/tabs/tab.h" -#include "chrome/browser/views/tabs/tab_strip.h" -#include "chrome/common/notification_service.h" -#include "gfx/canvas_skia.h" -#include "grit/theme_resources.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "views/event.h" -#include "views/widget/root_view.h" -#include "views/widget/widget.h" -#include "views/window/window.h" - -#if defined(OS_WIN) -#include "views/widget/widget_win.h" -#endif - -#if defined(OS_LINUX) -#include <gdk/gdk.h> -#include <gdk/gdkkeysyms.h> -#endif - -static const int kHorizontalMoveThreshold = 16; // Pixels. - -// Distance in pixels the user must move the mouse before we consider moving -// an attached vertical tab. -static const int kVerticalMoveThreshold = 8; - -// If non-null there is a drag underway. -static DraggedTabController* instance_; - -namespace { - -// Delay, in ms, during dragging before we bring a window to front. -const int kBringToFrontDelay = 750; - -// Radius of the rect drawn by DockView. -const int kRoundedRectRadius = 4; - -// Spacing between tab icons when DockView is showing a docking location that -// contains more than one tab. -const int kTabSpacing = 4; - -// DockView is the view responsible for giving a visual indicator of where a -// dock is going to occur. - -class DockView : public views::View { - public: - explicit DockView(DockInfo::Type type) : type_(type) {} - - virtual gfx::Size GetPreferredSize() { - return gfx::Size(DockInfo::popup_width(), DockInfo::popup_height()); - } - - virtual void PaintBackground(gfx::Canvas* canvas) { - SkRect outer_rect = { SkIntToScalar(0), SkIntToScalar(0), - SkIntToScalar(width()), - SkIntToScalar(height()) }; - - // Fill the background rect. - SkPaint paint; - paint.setColor(SkColorSetRGB(108, 108, 108)); - paint.setStyle(SkPaint::kFill_Style); - canvas->AsCanvasSkia()->drawRoundRect( - outer_rect, SkIntToScalar(kRoundedRectRadius), - SkIntToScalar(kRoundedRectRadius), paint); - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - - SkBitmap* high_icon = rb.GetBitmapNamed(IDR_DOCK_HIGH); - SkBitmap* wide_icon = rb.GetBitmapNamed(IDR_DOCK_WIDE); - - canvas->Save(); - bool rtl_ui = base::i18n::IsRTL(); - if (rtl_ui) { - // Flip canvas to draw the mirrored tab images for RTL UI. - canvas->TranslateInt(width(), 0); - canvas->ScaleInt(-1, 1); - } - int x_of_active_tab = width() / 2 + kTabSpacing / 2; - int x_of_inactive_tab = width() / 2 - high_icon->width() - kTabSpacing / 2; - switch (type_) { - case DockInfo::LEFT_OF_WINDOW: - case DockInfo::LEFT_HALF: - if (!rtl_ui) - std::swap(x_of_active_tab, x_of_inactive_tab); - canvas->DrawBitmapInt(*high_icon, x_of_active_tab, - (height() - high_icon->height()) / 2); - if (type_ == DockInfo::LEFT_OF_WINDOW) { - DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, - (height() - high_icon->height()) / 2); - } - break; - - - case DockInfo::RIGHT_OF_WINDOW: - case DockInfo::RIGHT_HALF: - if (rtl_ui) - std::swap(x_of_active_tab, x_of_inactive_tab); - canvas->DrawBitmapInt(*high_icon, x_of_active_tab, - (height() - high_icon->height()) / 2); - if (type_ == DockInfo::RIGHT_OF_WINDOW) { - DrawBitmapWithAlpha(canvas, *high_icon, x_of_inactive_tab, - (height() - high_icon->height()) / 2); - } - break; - - case DockInfo::TOP_OF_WINDOW: - canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, - height() / 2 - high_icon->height()); - break; - - case DockInfo::MAXIMIZE: { - SkBitmap* max_icon = rb.GetBitmapNamed(IDR_DOCK_MAX); - canvas->DrawBitmapInt(*max_icon, (width() - max_icon->width()) / 2, - (height() - max_icon->height()) / 2); - break; - } - - case DockInfo::BOTTOM_HALF: - case DockInfo::BOTTOM_OF_WINDOW: - canvas->DrawBitmapInt(*wide_icon, (width() - wide_icon->width()) / 2, - height() / 2 + kTabSpacing / 2); - if (type_ == DockInfo::BOTTOM_OF_WINDOW) { - DrawBitmapWithAlpha(canvas, *wide_icon, - (width() - wide_icon->width()) / 2, - height() / 2 - kTabSpacing / 2 - wide_icon->height()); - } - break; - - default: - NOTREACHED(); - break; - } - canvas->Restore(); - } - - private: - void DrawBitmapWithAlpha(gfx::Canvas* canvas, const SkBitmap& image, - int x, int y) { - SkPaint paint; - paint.setAlpha(128); - canvas->DrawBitmapInt(image, x, y, paint); - } - - DockInfo::Type type_; - - DISALLOW_COPY_AND_ASSIGN(DockView); -}; - -gfx::Point ConvertScreenPointToTabStripPoint(BaseTabStrip* tabstrip, - const gfx::Point& screen_point) { - gfx::Point tabstrip_topleft; - views::View::ConvertPointToScreen(tabstrip, &tabstrip_topleft); - return gfx::Point(screen_point.x() - tabstrip_topleft.x(), - screen_point.y() - tabstrip_topleft.y()); -} - -// Returns the the x-coordinate of |point| if the type of tabstrip is horizontal -// otherwise returns the y-coordinate. -int MajorAxisValue(const gfx::Point& point, BaseTabStrip* tabstrip) { - return (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) ? - point.x() : point.y(); -} - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// DockDisplayer - -// DockDisplayer is responsible for giving the user a visual indication of a -// possible dock position (as represented by DockInfo). DockDisplayer shows -// a window with a DockView in it. Two animations are used that correspond to -// the state of DockInfo::in_enable_area. -class DraggedTabController::DockDisplayer : public AnimationDelegate { - public: - DockDisplayer(DraggedTabController* controller, - const DockInfo& info) - : controller_(controller), - popup_(NULL), - popup_view_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST(animation_(this)), - hidden_(false), - in_enable_area_(info.in_enable_area()) { -#if defined(OS_WIN) - views::WidgetWin* popup = new views::WidgetWin; - popup_ = popup; - popup->set_window_style(WS_POPUP); - popup->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW | - WS_EX_TOPMOST); - popup->SetOpacity(0x00); - popup->Init(NULL, info.GetPopupRect()); - popup->SetContentsView(new DockView(info.type())); - if (info.in_enable_area()) - animation_.Reset(1); - else - animation_.Show(); - popup->SetWindowPos(HWND_TOP, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOMOVE | SWP_SHOWWINDOW); -#else - NOTIMPLEMENTED(); -#endif - popup_view_ = popup_->GetNativeView(); - } - - ~DockDisplayer() { - if (controller_) - controller_->DockDisplayerDestroyed(this); - } - - // Updates the state based on |in_enable_area|. - void UpdateInEnabledArea(bool in_enable_area) { - if (in_enable_area != in_enable_area_) { - in_enable_area_ = in_enable_area; - UpdateLayeredAlpha(); - } - } - - // Resets the reference to the hosting DraggedTabController. This is invoked - // when the DraggedTabController is destoryed. - void clear_controller() { controller_ = NULL; } - - // NativeView of the window we create. - gfx::NativeView popup_view() { return popup_view_; } - - // Starts the hide animation. When the window is closed the - // DraggedTabController is notified by way of the DockDisplayerDestroyed - // method - void Hide() { - if (hidden_) - return; - - if (!popup_) { - delete this; - return; - } - hidden_ = true; - animation_.Hide(); - } - - virtual void AnimationProgressed(const Animation* animation) { - UpdateLayeredAlpha(); - } - - virtual void AnimationEnded(const Animation* animation) { - if (!hidden_) - return; -#if defined(OS_WIN) - static_cast<views::WidgetWin*>(popup_)->Close(); -#else - NOTIMPLEMENTED(); -#endif - delete this; - } - - virtual void UpdateLayeredAlpha() { -#if defined(OS_WIN) - double scale = in_enable_area_ ? 1 : .5; - static_cast<views::WidgetWin*>(popup_)->SetOpacity( - static_cast<BYTE>(animation_.GetCurrentValue() * scale * 255.0)); - popup_->GetRootView()->SchedulePaint(); -#else - NOTIMPLEMENTED(); -#endif - } - - private: - // DraggedTabController that created us. - DraggedTabController* controller_; - - // Window we're showing. - views::Widget* popup_; - - // NativeView of |popup_|. We cache this to avoid the possibility of - // invoking a method on popup_ after we close it. - gfx::NativeView popup_view_; - - // Animation for when first made visible. - SlideAnimation animation_; - - // Have we been hidden? - bool hidden_; - - // Value of DockInfo::in_enable_area. - bool in_enable_area_; -}; - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, public: - -DraggedTabController::DraggedTabController(BaseTab* source_tab, - BaseTabStrip* source_tabstrip) - : dragged_contents_(NULL), - original_delegate_(NULL), - source_tabstrip_(source_tabstrip), - source_model_index_(source_tabstrip->GetModelIndexOfBaseTab(source_tab)), - attached_tabstrip_(NULL), - attached_tab_(NULL), - offset_to_width_ratio_(0), - old_focused_view_(NULL), - last_move_screen_loc_(0), - mini_(source_tab->data().mini), - pinned_(source_tabstrip->IsTabPinned(source_tab)), - started_drag_(false), - active_(true) { - instance_ = this; - SetDraggedContents( - GetModel(source_tabstrip_)->GetTabContentsAt(source_model_index_)); - // Listen for Esc key presses. - MessageLoopForUI::current()->AddObserver(this); -} - -DraggedTabController::~DraggedTabController() { - if (instance_ == this) - instance_ = NULL; - - MessageLoopForUI::current()->RemoveObserver(this); - // Need to delete the view here manually _before_ we reset the dragged - // contents to NULL, otherwise if the view is animating to its destination - // bounds, it won't be able to clean up properly since its cleanup routine - // uses GetIndexForDraggedContents, which will be invalid. - view_.reset(NULL); - SetDraggedContents(NULL); // This removes our observer. -} - -// static -bool DraggedTabController::IsAttachedTo(BaseTabStrip* tab_strip) { - return instance_ && instance_->active_ && - instance_->attached_tabstrip_ == tab_strip; -} - -void DraggedTabController::CaptureDragInfo(views::View* tab, - const gfx::Point& mouse_offset) { - if (tab->width() > 0) { - offset_to_width_ratio_ = static_cast<float>(mouse_offset.x()) / - static_cast<float>(tab->width()); - } - start_screen_point_ = GetCursorScreenPoint(); - mouse_offset_ = mouse_offset; - InitWindowCreatePoint(); -} - -void DraggedTabController::Drag() { - bring_to_front_timer_.Stop(); - - // Before we get to dragging anywhere, ensure that we consider ourselves - // attached to the source tabstrip. - if (!started_drag_ && CanStartDrag()) { - started_drag_ = true; - SaveFocus(); - Attach(source_tabstrip_, gfx::Point()); - } - - if (started_drag_) - ContinueDragging(); -} - -void DraggedTabController::EndDrag(bool canceled) { - EndDragImpl(canceled ? CANCELED : NORMAL); -} - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, PageNavigator implementation: - -void DraggedTabController::OpenURLFromTab(TabContents* source, - const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition) { - if (original_delegate_) { - if (disposition == CURRENT_TAB) - disposition = NEW_WINDOW; - - original_delegate_->OpenURLFromTab(source, url, referrer, - disposition, transition); - } -} - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, TabContentsDelegate implementation: - -void DraggedTabController::NavigationStateChanged(const TabContents* source, - unsigned changed_flags) { - if (view_.get()) - view_->Update(); -} - -void DraggedTabController::AddNewContents(TabContents* source, - TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture) { - DCHECK(disposition != CURRENT_TAB); - - // Theoretically could be called while dragging if the page tries to - // spawn a window. Route this message back to the browser in most cases. - if (original_delegate_) { - original_delegate_->AddNewContents(source, new_contents, disposition, - initial_pos, user_gesture); - } -} - -void DraggedTabController::ActivateContents(TabContents* contents) { - // Ignored. -} - -void DraggedTabController::DeactivateContents(TabContents* contents) { - // Ignored. -} - -void DraggedTabController::LoadingStateChanged(TabContents* source) { - // It would be nice to respond to this message by changing the - // screen shot in the dragged tab. - if (view_.get()) - view_->Update(); -} - -void DraggedTabController::CloseContents(TabContents* source) { - // Theoretically could be called by a window. Should be ignored - // because window.close() is ignored (usually, even though this - // method gets called.) -} - -void DraggedTabController::MoveContents(TabContents* source, - const gfx::Rect& pos) { - // Theoretically could be called by a web page trying to move its - // own window. Should be ignored since we're moving the window... -} - -void DraggedTabController::ToolbarSizeChanged(TabContents* source, - bool finished) { - // Dragged tabs don't care about this. -} - -void DraggedTabController::URLStarredChanged(TabContents* source, - bool starred) { - // Ignored. -} - -void DraggedTabController::UpdateTargetURL(TabContents* source, - const GURL& url) { - // Ignored. -} - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, NotificationObserver implementation: - -void DraggedTabController::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); - DCHECK(Source<TabContents>(source).ptr() == dragged_contents_); - EndDragImpl(TAB_DESTROYED); -} - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, MessageLoop::Observer implementation: - -#if defined(OS_WIN) -void DraggedTabController::WillProcessMessage(const MSG& msg) { -} - -void DraggedTabController::DidProcessMessage(const MSG& msg) { - // If the user presses ESC during a drag, we need to abort and revert things - // to the way they were. This is the most reliable way to do this since no - // single view or window reliably receives events throughout all the various - // kinds of tab dragging. - if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) - EndDrag(true); -} -#else -void DraggedTabController::WillProcessEvent(GdkEvent* event) { -} - -void DraggedTabController::DidProcessEvent(GdkEvent* event) { - if (event->type == GDK_KEY_PRESS && - reinterpret_cast<GdkEventKey*>(event)->keyval == GDK_Escape) { - EndDrag(true); - } -} -#endif - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabController, private: - -void DraggedTabController::InitWindowCreatePoint() { - // window_create_point_ is only used in CompleteDrag() (through - // GetWindowCreatePoint() to get the start point of the docked window) when - // the attached_tabstrip_ is NULL and all the window's related bound - // information are obtained from source_tabstrip_. So, we need to get the - // first_tab based on source_tabstrip_, not attached_tabstrip_. Otherwise, - // the window_create_point_ is not in the correct coordinate system. Please - // refer to http://crbug.com/6223 comment #15 for detailed information. - views::View* first_tab = source_tabstrip_->base_tab_at_tab_index(0); - views::View::ConvertPointToWidget(first_tab, &first_source_tab_point_); - UpdateWindowCreatePoint(); -} - -void DraggedTabController::UpdateWindowCreatePoint() { - // See comments in InitWindowCreatePoint for details on this. - window_create_point_ = first_source_tab_point_; - window_create_point_.Offset(mouse_offset_.x(), mouse_offset_.y()); -} - -gfx::Point DraggedTabController::GetWindowCreatePoint() const { - gfx::Point cursor_point = GetCursorScreenPoint(); - if (dock_info_.type() != DockInfo::NONE) { - // If we're going to dock, we need to return the exact coordinate, - // otherwise we may attempt to maximize on the wrong monitor. - return cursor_point; - } - return gfx::Point(cursor_point.x() - window_create_point_.x(), - cursor_point.y() - window_create_point_.y()); -} - -void DraggedTabController::UpdateDockInfo(const gfx::Point& screen_point) { - // Update the DockInfo for the current mouse coordinates. - DockInfo dock_info = GetDockInfoAtPoint(screen_point); - if (source_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && - ((dock_info.type() == DockInfo::LEFT_OF_WINDOW && - !base::i18n::IsRTL()) || - (dock_info.type() == DockInfo::RIGHT_OF_WINDOW && - base::i18n::IsRTL()))) { - // For side tabs it's way to easy to trigger to docking along the left/right - // edge, so we disable it. - dock_info = DockInfo(); - } - if (!dock_info.equals(dock_info_)) { - // DockInfo for current position differs. - if (dock_info_.type() != DockInfo::NONE && - !dock_controllers_.empty()) { - // Hide old visual indicator. - dock_controllers_.back()->Hide(); - } - dock_info_ = dock_info; - if (dock_info_.type() != DockInfo::NONE) { - // Show new docking position. - DockDisplayer* controller = new DockDisplayer(this, dock_info_); - if (controller->popup_view()) { - dock_controllers_.push_back(controller); - dock_windows_.insert(controller->popup_view()); - } else { - delete controller; - } - } - } else if (dock_info_.type() != DockInfo::NONE && - !dock_controllers_.empty()) { - // Current dock position is the same as last, update the controller's - // in_enable_area state as it may have changed. - dock_controllers_.back()->UpdateInEnabledArea(dock_info_.in_enable_area()); - } -} - -void DraggedTabController::SetDraggedContents(TabContents* new_contents) { - if (dragged_contents_) { - registrar_.Remove(this, - NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(dragged_contents_)); - if (original_delegate_) - dragged_contents_->set_delegate(original_delegate_); - } - original_delegate_ = NULL; - dragged_contents_ = new_contents; - if (dragged_contents_) { - registrar_.Add(this, - NotificationType::TAB_CONTENTS_DESTROYED, - Source<TabContents>(dragged_contents_)); - - // We need to be the delegate so we receive messages about stuff, - // otherwise our dragged_contents() may be replaced and subsequently - // collected/destroyed while the drag is in process, leading to - // nasty crashes. - original_delegate_ = dragged_contents_->delegate(); - dragged_contents_->set_delegate(this); - } -} - -void DraggedTabController::SaveFocus() { - if (!old_focused_view_) { - old_focused_view_ = source_tabstrip_->GetRootView()->GetFocusedView(); - source_tabstrip_->GetRootView()->FocusView(source_tabstrip_); - } -} - -void DraggedTabController::RestoreFocus() { - if (old_focused_view_ && attached_tabstrip_ == source_tabstrip_) - old_focused_view_->GetRootView()->FocusView(old_focused_view_); - old_focused_view_ = NULL; -} - -bool DraggedTabController::CanStartDrag() const { - // Determine if the mouse has moved beyond a minimum elasticity distance in - // any direction from the starting point. - static const int kMinimumDragDistance = 10; - gfx::Point screen_point = GetCursorScreenPoint(); - int x_offset = abs(screen_point.x() - start_screen_point_.x()); - int y_offset = abs(screen_point.y() - start_screen_point_.y()); - return sqrt(pow(static_cast<float>(x_offset), 2) + - pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; -} - -void DraggedTabController::ContinueDragging() { - // Note that the coordinates given to us by |drag_event| are basically - // useless, since they're in source_tab_ coordinates. On the surface, you'd - // think we could just convert them to screen coordinates, however in the - // situation where we're dragging the last tab in a window when multiple - // windows are open, the coordinates of |source_tab_| are way off in - // hyperspace since the window was moved there instead of being closed so - // that we'd keep receiving events. And our ConvertPointToScreen methods - // aren't really multi-screen aware. So really it's just safer to get the - // actual position of the mouse cursor directly from Windows here, which is - // guaranteed to be correct regardless of monitor config. - gfx::Point screen_point = GetCursorScreenPoint(); - -#if defined(OS_CHROMEOS) - // We don't allow detaching in chrome os. - BaseTabStrip* target_tabstrip = source_tabstrip_; -#else - // Determine whether or not we have dragged over a compatible TabStrip in - // another browser window. If we have, we should attach to it and start - // dragging within it. - BaseTabStrip* target_tabstrip = GetTabStripForPoint(screen_point); -#endif - if (target_tabstrip != attached_tabstrip_) { - // Make sure we're fully detached from whatever TabStrip we're attached to - // (if any). - if (attached_tabstrip_) - Detach(); - if (target_tabstrip) - Attach(target_tabstrip, screen_point); - } - if (!target_tabstrip) { - bring_to_front_timer_.Start( - base::TimeDelta::FromMilliseconds(kBringToFrontDelay), this, - &DraggedTabController::BringWindowUnderMouseToFront); - } - - UpdateDockInfo(screen_point); - - if (attached_tabstrip_) - MoveAttachedTab(screen_point); - else - MoveDetachedTab(screen_point); -} - -void DraggedTabController::MoveAttachedTab(const gfx::Point& screen_point) { - DCHECK(attached_tabstrip_); - DCHECK(!view_.get()); - - gfx::Point dragged_view_point = GetAttachedTabDragPoint(screen_point); - TabStripModel* attached_model = GetModel(attached_tabstrip_); - int from_index = attached_model->GetIndexOfTabContents(dragged_contents_); - - int threshold = kVerticalMoveThreshold; - if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - TabStrip* tab_strip = static_cast<TabStrip*>(attached_tabstrip_); - - // Determine the horizontal move threshold. This is dependent on the width - // of tabs. The smaller the tabs compared to the standard size, the smaller - // the threshold. - double unselected, selected; - tab_strip->GetCurrentTabWidths(&unselected, &selected); - double ratio = unselected / Tab::GetStandardSize().width(); - threshold = static_cast<int>(ratio * kHorizontalMoveThreshold); - } - - // Update the model, moving the TabContents from one index to another. Do this - // only if we have moved a minimum distance since the last reorder (to prevent - // jitter). - if (abs(MajorAxisValue(screen_point, attached_tabstrip_) - - last_move_screen_loc_) > threshold) { - gfx::Point dragged_view_screen_point(dragged_view_point); - views::View::ConvertPointToScreen(attached_tabstrip_, - &dragged_view_screen_point); - gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_screen_point); - int to_index = GetInsertionIndexForDraggedBounds(bounds, true); - to_index = NormalizeIndexToAttachedTabStrip(to_index); - if (from_index != to_index) { - last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip_); - attached_model->MoveTabContentsAt(from_index, to_index, true); - } - } - - attached_tab_->SchedulePaint(); - attached_tab_->SetX(dragged_view_point.x()); - attached_tab_->SetX( - attached_tabstrip_->MirroredLeftPointForRect(attached_tab_->bounds())); - attached_tab_->SetY(dragged_view_point.y()); - attached_tab_->SchedulePaint(); -} - -void DraggedTabController::MoveDetachedTab(const gfx::Point& screen_point) { - DCHECK(!attached_tabstrip_); - DCHECK(view_.get()); - - int x = screen_point.x() - mouse_offset_.x(); - int y = screen_point.y() - mouse_offset_.y(); - - // Move the View. There are no changes to the model if we're detached. - view_->MoveTo(gfx::Point(x, y)); -} - -DockInfo DraggedTabController::GetDockInfoAtPoint( - const gfx::Point& screen_point) { - if (attached_tabstrip_) { - // If the mouse is over a tab strip, don't offer a dock position. - return DockInfo(); - } - - if (dock_info_.IsValidForPoint(screen_point)) { - // It's possible any given screen coordinate has multiple docking - // positions. Check the current info first to avoid having the docking - // position bounce around. - return dock_info_; - } - - gfx::NativeView dragged_hwnd = view_->GetWidget()->GetNativeView(); - dock_windows_.insert(dragged_hwnd); - DockInfo info = DockInfo::GetDockInfoAtPoint(screen_point, dock_windows_); - dock_windows_.erase(dragged_hwnd); - return info; -} - -BaseTabStrip* DraggedTabController::GetTabStripForPoint( - const gfx::Point& screen_point) { - gfx::NativeView dragged_view = NULL; - if (view_.get()) { - dragged_view = view_->GetWidget()->GetNativeView(); - dock_windows_.insert(dragged_view); - } - gfx::NativeWindow local_window = - DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_); - if (dragged_view) - dock_windows_.erase(dragged_view); - if (!local_window) - return NULL; - BrowserView* browser = - BrowserView::GetBrowserViewForNativeWindow(local_window); - // We don't allow drops on windows that don't have tabstrips. - if (!browser || - !browser->browser()->SupportsWindowFeature(Browser::FEATURE_TABSTRIP)) - return NULL; - - BaseTabStrip* other_tabstrip = browser->tabstrip(); - if (!other_tabstrip->controller()->IsCompatibleWith(source_tabstrip_)) - return NULL; - return GetTabStripIfItContains(other_tabstrip, screen_point); -} - -BaseTabStrip* DraggedTabController::GetTabStripIfItContains( - BaseTabStrip* tabstrip, const gfx::Point& screen_point) const { - static const int kVerticalDetachMagnetism = 15; - static const int kHorizontalDetachMagnetism = 15; - // Make sure the specified screen point is actually within the bounds of the - // specified tabstrip... - gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip); - if (tabstrip->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - if (screen_point.x() < tabstrip_bounds.right() && - screen_point.x() >= tabstrip_bounds.x()) { - // TODO(beng): make this be relative to the start position of the mouse - // for the source TabStrip. - int upper_threshold = tabstrip_bounds.bottom() + kVerticalDetachMagnetism; - int lower_threshold = tabstrip_bounds.y() - kVerticalDetachMagnetism; - if (screen_point.y() >= lower_threshold && - screen_point.y() <= upper_threshold) { - return tabstrip; - } - } - } else { - if (screen_point.y() < tabstrip_bounds.bottom() && - screen_point.y() >= tabstrip_bounds.y()) { - int upper_threshold = tabstrip_bounds.right() + - kHorizontalDetachMagnetism; - int lower_threshold = tabstrip_bounds.x() - kHorizontalDetachMagnetism; - if (screen_point.x() >= lower_threshold && - screen_point.x() <= upper_threshold) { - return tabstrip; - } - } - } - return NULL; -} - -void DraggedTabController::Attach(BaseTabStrip* attached_tabstrip, - const gfx::Point& screen_point) { - DCHECK(!attached_tabstrip_); // We should already have detached by the time - // we get here. - DCHECK(!attached_tab_); // Similarly there should be no attached tab. - - attached_tabstrip_ = attached_tabstrip; - - // We don't need the photo-booth while we're attached. - photobooth_.reset(NULL); - - // And we don't need the dragged view. - view_.reset(); - - BaseTab* tab = GetTabMatchingDraggedContents(attached_tabstrip_); - - if (!tab) { - // There is no Tab in |attached_tabstrip| that corresponds to the dragged - // TabContents. We must now create one. - - // Remove ourselves as the delegate now that the dragged TabContents is - // being inserted back into a Browser. - dragged_contents_->set_delegate(NULL); - original_delegate_ = NULL; - - // Return the TabContents' to normalcy. - dragged_contents_->set_capturing_contents(false); - - // Inserting counts as a move. We don't want the tabs to jitter when the - // user moves the tab immediately after attaching it. - last_move_screen_loc_ = MajorAxisValue(screen_point, attached_tabstrip); - - // Figure out where to insert the tab based on the bounds of the dragged - // representation and the ideal bounds of the other Tabs already in the - // strip. ("ideal bounds" are stable even if the Tabs' actual bounds are - // changing due to animation). - gfx::Rect bounds = GetDraggedViewTabStripBounds(screen_point); - int index = GetInsertionIndexForDraggedBounds(bounds, false); - attached_tabstrip_->set_attaching_dragged_tab(true); - GetModel(attached_tabstrip_)->InsertTabContentsAt( - index, dragged_contents_, - TabStripModel::ADD_SELECTED | - (pinned_ ? TabStripModel::ADD_PINNED : 0)); - attached_tabstrip_->set_attaching_dragged_tab(false); - - tab = GetTabMatchingDraggedContents(attached_tabstrip_); - } - DCHECK(tab); // We should now have a tab. - attached_tab_ = tab; - attached_tabstrip_->StartedDraggingTab(tab); - - if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - // The size of the dragged tab may have changed. Adjust the x offset so that - // ratio of mouse_offset_ to original width is maintained. - mouse_offset_.set_x(static_cast<int>(offset_to_width_ratio_ * - static_cast<int>(tab->width()))); - } - - // Move the corresponding window to the front. - attached_tabstrip_->GetWindow()->Activate(); -} - -void DraggedTabController::Detach() { - // Prevent the TabContents' HWND from being hidden by any of the model - // operations performed during the drag. - dragged_contents_->set_capturing_contents(true); - - // Update the Model. - TabRendererData tab_data = attached_tab_->data(); - TabStripModel* attached_model = GetModel(attached_tabstrip_); - int index = attached_model->GetIndexOfTabContents(dragged_contents_); - DCHECK(index != -1); - // Hide the tab so that the user doesn't see it animate closed. - attached_tab_->SetVisible(false); - int attached_tab_width = attached_tab_->width(); - attached_model->DetachTabContentsAt(index); - // Detaching may end up deleting the tab, drop references to it. - attached_tab_ = NULL; - - // If we've removed the last Tab from the TabStrip, hide the frame now. - if (attached_model->empty()) - HideFrame(); - - // Set up the photo booth to start capturing the contents of the dragged - // TabContents. - if (!photobooth_.get()) { - photobooth_.reset( - NativeViewPhotobooth::Create(dragged_contents_->GetNativeView())); - } - - // Create the dragged view. - EnsureDraggedView(tab_data); - view_->SetTabWidthAndUpdate(attached_tab_width, photobooth_.get()); - - // Detaching resets the delegate, but we still want to be the delegate. - dragged_contents_->set_delegate(this); - - attached_tabstrip_ = NULL; -} - -int DraggedTabController::GetInsertionIndexForDraggedBounds( - const gfx::Rect& dragged_bounds, - bool is_tab_attached) const { - int right_tab_x = 0; - int bottom_tab_y = 0; - - // If the UI layout of the tab strip is right-to-left, we need to mirror the - // bounds of the dragged tab before performing the drag/drop related - // calculations. We mirror the dragged bounds because we determine the - // position of each tab on the tab strip by calling GetBounds() (without the - // mirroring transformation flag) which effectively means that even though - // the tabs are rendered from right to left, the code performs the - // calculation as if the tabs are laid out from left to right. Mirroring the - // dragged bounds adjusts the coordinates of the tab we are dragging so that - // it uses the same orientation used by the tabs on the tab strip. - gfx::Rect adjusted_bounds(dragged_bounds); - adjusted_bounds.set_x( - attached_tabstrip_->MirroredLeftPointForRect(adjusted_bounds)); - - int index = -1; - for (int i = 0; i < attached_tabstrip_->tab_count(); ++i) { - const gfx::Rect& ideal_bounds = attached_tabstrip_->ideal_bounds(i); - if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - gfx::Rect left_half = ideal_bounds; - left_half.set_width(left_half.width() / 2); - gfx::Rect right_half = ideal_bounds; - right_half.set_width(ideal_bounds.width() - left_half.width()); - right_half.set_x(left_half.right()); - right_tab_x = right_half.right(); - if (adjusted_bounds.x() >= right_half.x() && - adjusted_bounds.x() < right_half.right()) { - index = i + 1; - break; - } else if (adjusted_bounds.x() >= left_half.x() && - adjusted_bounds.x() < left_half.right()) { - index = i; - break; - } - } else { - // Vertical tab strip. - int max_y = ideal_bounds.bottom(); - int mid_y = ideal_bounds.y() + ideal_bounds.height() / 2; - bottom_tab_y = max_y; - if (adjusted_bounds.y() < mid_y) { - index = i; - break; - } else if (adjusted_bounds.y() >= mid_y && adjusted_bounds.y() < max_y) { - index = i + 1; - break; - } - } - } - if (index == -1) { - if ((attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP && - adjusted_bounds.right() > right_tab_x) || - (attached_tabstrip_->type() == BaseTabStrip::VERTICAL_TAB_STRIP && - adjusted_bounds.y() >= bottom_tab_y)) { - index = GetModel(attached_tabstrip_)->count(); - } else { - index = 0; - } - } - - index = GetModel(attached_tabstrip_)->ConstrainInsertionIndex(index, mini_); - if (is_tab_attached && mini_ && - index == GetModel(attached_tabstrip_)->IndexOfFirstNonMiniTab()) { - index--; - } - return index; -} - -gfx::Rect DraggedTabController::GetDraggedViewTabStripBounds( - const gfx::Point& screen_point) { - gfx::Point client_point = - ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point); - // attached_tab_ is NULL when inserting into a new tabstrip. - if (attached_tab_) { - return gfx::Rect(client_point.x(), client_point.y(), - attached_tab_->width(), attached_tab_->height()); - } - - if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - double sel_width, unselected_width; - static_cast<TabStrip*>(attached_tabstrip_)->GetCurrentTabWidths( - &sel_width, &unselected_width); - return gfx::Rect(client_point.x(), client_point.y(), - static_cast<int>(sel_width), - Tab::GetStandardSize().height()); - } - - return gfx::Rect(client_point.x(), client_point.y(), - attached_tabstrip_->width(), - SideTab::GetPreferredHeight()); -} - -gfx::Point DraggedTabController::GetAttachedTabDragPoint( - const gfx::Point& screen_point) { - DCHECK(attached_tabstrip_); // The tab must be attached. - - int x = screen_point.x() - mouse_offset_.x(); - int y = screen_point.y() - mouse_offset_.y(); - - gfx::Point tab_loc(x, y); - views::View::ConvertPointToView(NULL, attached_tabstrip_, &tab_loc); - - x = tab_loc.x(); - y = tab_loc.y(); - - const gfx::Size& tab_size = attached_tab_->bounds().size(); - - if (attached_tabstrip_->type() == BaseTabStrip::HORIZONTAL_TAB_STRIP) { - int max_x = attached_tabstrip_->bounds().right() - tab_size.width(); - x = std::min(std::max(x, 0), max_x); - y = 0; - } else { - x = SideTabStrip::kTabStripInset; - int max_y = attached_tabstrip_->bounds().bottom() - tab_size.height(); - y = std::min(std::max(y, SideTabStrip::kTabStripInset), max_y); - } - return gfx::Point(x, y); -} - -BaseTab* DraggedTabController::GetTabMatchingDraggedContents( - BaseTabStrip* tabstrip) const { - int model_index = - GetModel(tabstrip)->GetIndexOfTabContents(dragged_contents_); - return model_index == TabStripModel::kNoTab ? - NULL : tabstrip->GetBaseTabAtModelIndex(model_index); -} - -void DraggedTabController::EndDragImpl(EndDragType type) { - // WARNING: this may be invoked multiple times. In particular, if deletion - // occurs after a delay (as it does when the tab is released in the original - // tab strip) and the navigation controller/tab contents is deleted before - // the animation finishes, this is invoked twice. The second time through - // type == TAB_DESTROYED. - - active_ = false; - - bring_to_front_timer_.Stop(); - - // Hide the current dock controllers. - for (size_t i = 0; i < dock_controllers_.size(); ++i) { - // Be sure and clear the controller first, that way if Hide ends up - // deleting the controller it won't call us back. - dock_controllers_[i]->clear_controller(); - dock_controllers_[i]->Hide(); - } - dock_controllers_.clear(); - dock_windows_.clear(); - - if (type != TAB_DESTROYED) { - // We only finish up the drag if we were actually dragging. If start_drag_ - // is false, the user just clicked and released and didn't move the mouse - // enough to trigger a drag. - if (started_drag_) { - RestoreFocus(); - if (type == CANCELED) - RevertDrag(); - else - CompleteDrag(); - } - if (dragged_contents_ && dragged_contents_->delegate() == this) - dragged_contents_->set_delegate(original_delegate_); - } else { - // If we get here it means the NavigationController is going down. Don't - // attempt to do any cleanup other than resetting the delegate (if we're - // still the delegate). - if (dragged_contents_ && dragged_contents_->delegate() == this) - dragged_contents_->set_delegate(NULL); - dragged_contents_ = NULL; - } - - // The delegate of the dragged contents should have been reset. Unset the - // original delegate so that we don't attempt to reset the delegate when - // deleted. - DCHECK(!dragged_contents_ || dragged_contents_->delegate() != this); - original_delegate_ = NULL; - - source_tabstrip_->DestroyDragController(); -} - -void DraggedTabController::RevertDrag() { - DCHECK(started_drag_); - - // We save this here because code below will modify |attached_tabstrip_|. - bool restore_frame = attached_tabstrip_ != source_tabstrip_; - if (attached_tabstrip_) { - int index = GetModel(attached_tabstrip_)->GetIndexOfTabContents( - dragged_contents_); - if (attached_tabstrip_ != source_tabstrip_) { - // The Tab was inserted into another TabStrip. We need to put it back - // into the original one. - GetModel(attached_tabstrip_)->DetachTabContentsAt(index); - // TODO(beng): (Cleanup) seems like we should use Attach() for this - // somehow. - attached_tabstrip_ = source_tabstrip_; - GetModel(source_tabstrip_)->InsertTabContentsAt( - source_model_index_, dragged_contents_, - TabStripModel::ADD_SELECTED | - (pinned_ ? TabStripModel::ADD_PINNED : 0)); - } else { - // The Tab was moved within the TabStrip where the drag was initiated. - // Move it back to the starting location. - GetModel(source_tabstrip_)->MoveTabContentsAt(index, source_model_index_, - true); - source_tabstrip_->StoppedDraggingTab(attached_tab_); - } - } else { - // TODO(beng): (Cleanup) seems like we should use Attach() for this - // somehow. - attached_tabstrip_ = source_tabstrip_; - // The Tab was detached from the TabStrip where the drag began, and has not - // been attached to any other TabStrip. We need to put it back into the - // source TabStrip. - GetModel(source_tabstrip_)->InsertTabContentsAt( - source_model_index_, dragged_contents_, - TabStripModel::ADD_SELECTED | - (pinned_ ? TabStripModel::ADD_PINNED : 0)); - } - - // If we're not attached to any TabStrip, or attached to some other TabStrip, - // we need to restore the bounds of the original TabStrip's frame, in case - // it has been hidden. - if (restore_frame) { - if (!restore_bounds_.IsEmpty()) { -#if defined(OS_WIN) - HWND frame_hwnd = source_tabstrip_->GetWidget()->GetNativeView(); - MoveWindow(frame_hwnd, restore_bounds_.x(), restore_bounds_.y(), - restore_bounds_.width(), restore_bounds_.height(), TRUE); -#else - NOTIMPLEMENTED(); -#endif - } - } -} - -void DraggedTabController::CompleteDrag() { - DCHECK(started_drag_); - - if (attached_tabstrip_) { - attached_tabstrip_->StoppedDraggingTab(attached_tab_); - } else { - if (dock_info_.type() != DockInfo::NONE) { - Profile* profile = GetModel(source_tabstrip_)->profile(); - switch (dock_info_.type()) { - case DockInfo::LEFT_OF_WINDOW: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Left"), - profile); - break; - - case DockInfo::RIGHT_OF_WINDOW: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Right"), - profile); - break; - - case DockInfo::BOTTOM_OF_WINDOW: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Bottom"), - profile); - break; - - case DockInfo::TOP_OF_WINDOW: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Top"), - profile); - break; - - case DockInfo::MAXIMIZE: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_Maximize"), - profile); - break; - - case DockInfo::LEFT_HALF: - UserMetrics::RecordAction(UserMetricsAction("DockingWindow_LeftHalf"), - profile); - break; - - case DockInfo::RIGHT_HALF: - UserMetrics::RecordAction( - UserMetricsAction("DockingWindow_RightHalf"), - profile); - break; - - case DockInfo::BOTTOM_HALF: - UserMetrics::RecordAction( - UserMetricsAction("DockingWindow_BottomHalf"), - profile); - break; - - default: - NOTREACHED(); - break; - } - } - // Compel the model to construct a new window for the detached TabContents. - views::Window* window = source_tabstrip_->GetWindow(); - gfx::Rect window_bounds(window->GetNormalBounds()); - window_bounds.set_origin(GetWindowCreatePoint()); - // When modifying the following if statement, please make sure not to - // introduce issue listed in http://crbug.com/6223 comment #11. - bool rtl_ui = base::i18n::IsRTL(); - bool has_dock_position = (dock_info_.type() != DockInfo::NONE); - if (rtl_ui && has_dock_position) { - // Mirror X axis so the docked tab is aligned using the mouse click as - // the top-right corner. - window_bounds.set_x(window_bounds.x() - window_bounds.width()); - } - Browser* new_browser = - GetModel(source_tabstrip_)->delegate()->CreateNewStripWithContents( - dragged_contents_, window_bounds, dock_info_, window->IsMaximized()); - TabStripModel* new_model = new_browser->tabstrip_model(); - new_model->SetTabPinned(new_model->GetIndexOfTabContents(dragged_contents_), - pinned_); - new_browser->window()->Show(); - } - - CleanUpHiddenFrame(); -} - -void DraggedTabController::EnsureDraggedView(const TabRendererData& data) { - if (!view_.get()) { - gfx::Rect tab_bounds; - dragged_contents_->GetContainerBounds(&tab_bounds); - BaseTab* renderer = source_tabstrip_->CreateTabForDragging(); - renderer->SetData(data); - // DraggedTabView takes ownership of renderer. - view_.reset(new DraggedTabView(renderer, mouse_offset_, - tab_bounds.size(), - Tab::GetMinimumSelectedSize())); - } -} - -gfx::Point DraggedTabController::GetCursorScreenPoint() const { -#if defined(OS_WIN) - DWORD pos = GetMessagePos(); - return gfx::Point(pos); -#else - gint x, y; - gdk_display_get_pointer(gdk_display_get_default(), NULL, &x, &y, NULL); - return gfx::Point(x, y); -#endif -} - -gfx::Rect DraggedTabController::GetViewScreenBounds(views::View* view) const { - gfx::Point view_topleft; - views::View::ConvertPointToScreen(view, &view_topleft); - gfx::Rect view_screen_bounds = view->GetLocalBounds(true); - view_screen_bounds.Offset(view_topleft.x(), view_topleft.y()); - return view_screen_bounds; -} - -int DraggedTabController::NormalizeIndexToAttachedTabStrip(int index) const { - DCHECK(attached_tabstrip_) << "Can only be called when attached!"; - TabStripModel* attached_model = GetModel(attached_tabstrip_); - if (index >= attached_model->count()) - return attached_model->count() - 1; - if (index == TabStripModel::kNoTab) - return 0; - return index; -} - -void DraggedTabController::HideFrame() { -#if defined(OS_WIN) - // We don't actually hide the window, rather we just move it way off-screen. - // If we actually hide it, we stop receiving drag events. - HWND frame_hwnd = source_tabstrip_->GetWidget()->GetNativeView(); - RECT wr; - GetWindowRect(frame_hwnd, &wr); - MoveWindow(frame_hwnd, 0xFFFF, 0xFFFF, wr.right - wr.left, - wr.bottom - wr.top, TRUE); - - // We also save the bounds of the window prior to it being moved, so that if - // the drag session is aborted we can restore them. - restore_bounds_ = gfx::Rect(wr); -#else - NOTIMPLEMENTED(); -#endif -} - -void DraggedTabController::CleanUpHiddenFrame() { - // If the model we started dragging from is now empty, we must ask the - // delegate to close the frame. - if (GetModel(source_tabstrip_)->empty()) - GetModel(source_tabstrip_)->delegate()->CloseFrameAfterDragSession(); -} - -void DraggedTabController::DockDisplayerDestroyed( - DockDisplayer* controller) { - DockWindows::iterator dock_i = - dock_windows_.find(controller->popup_view()); - if (dock_i != dock_windows_.end()) - dock_windows_.erase(dock_i); - else - NOTREACHED(); - - std::vector<DockDisplayer*>::iterator i = - std::find(dock_controllers_.begin(), dock_controllers_.end(), - controller); - if (i != dock_controllers_.end()) - dock_controllers_.erase(i); - else - NOTREACHED(); -} - -void DraggedTabController::BringWindowUnderMouseToFront() { - // If we're going to dock to another window, bring it to the front. - gfx::NativeWindow window = dock_info_.window(); - if (!window) { - gfx::NativeView dragged_view = view_->GetWidget()->GetNativeView(); - dock_windows_.insert(dragged_view); - window = DockInfo::GetLocalProcessWindowAtPoint(GetCursorScreenPoint(), - dock_windows_); - dock_windows_.erase(dragged_view); - } - if (window) { -#if defined(OS_WIN) - // Move the window to the front. - SetWindowPos(window, HWND_TOP, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - - // The previous call made the window appear on top of the dragged window, - // move the dragged window to the front. - SetWindowPos(view_->GetWidget()->GetNativeView(), HWND_TOP, 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); -#else - NOTIMPLEMENTED(); -#endif - } -} - -TabStripModel* DraggedTabController::GetModel(BaseTabStrip* tabstrip) const { - return static_cast<BrowserTabStripController*>(tabstrip->controller())-> - model(); -} diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index 5c9c619..e445018 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -6,334 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_CONTROLLER_H_ #pragma once -#include "base/message_loop.h" -#include "base/scoped_ptr.h" -#include "base/timer.h" -#include "chrome/browser/dock_info.h" -#include "chrome/browser/tab_contents/tab_contents_delegate.h" -#include "chrome/common/notification_observer.h" -#include "chrome/common/notification_registrar.h" -#include "gfx/rect.h" - -namespace views { -class View; -} -class BaseTab; -class BaseTabStrip; -class DraggedTabView; -class NativeViewPhotobooth; -class TabStripModel; - -struct TabRendererData; - -/////////////////////////////////////////////////////////////////////////////// -// -// DraggedTabController -// -// An object that handles a drag session for an individual Tab within a -// TabStrip. This object is created whenever the mouse is pressed down on a -// Tab and destroyed when the mouse is released or the drag operation is -// aborted. The Tab that the user dragged (the "source tab") owns this object -// and must be the only one to destroy it (via |DestroyDragController|). -// -/////////////////////////////////////////////////////////////////////////////// -class DraggedTabController : public TabContentsDelegate, - public NotificationObserver, - public MessageLoopForUI::Observer { - public: - DraggedTabController(BaseTab* source_tab, - BaseTabStrip* source_tabstrip); - virtual ~DraggedTabController(); - - // Returns true if there is a drag underway and the drag is attached to - // |tab_strip|. - // NOTE: this returns false if the dragged tab controller is in the process - // of finishing the drag. - static bool IsAttachedTo(BaseTabStrip* tab_strip); - - // Capture information needed to be used during a drag session for this - // controller's associated source tab and BaseTabStrip. |mouse_offset| is the - // distance of the mouse pointer from the tab's origin. - void CaptureDragInfo(views::View* tab, const gfx::Point& mouse_offset); - - // Responds to drag events subsequent to StartDrag. If the mouse moves a - // sufficient distance before the mouse is released, a drag session is - // initiated. - void Drag(); - - // Complete the current drag session. If the drag session was canceled - // because the user pressed Escape or something interrupted it, |canceled| - // is true so the helper can revert the state to the world before the drag - // begun. - void EndDrag(bool canceled); - - TabContents* dragged_contents() { return dragged_contents_; } - - // Returns true if a drag started. - bool started_drag() const { return started_drag_; } - - private: - class DockDisplayer; - friend class DockDisplayer; - - typedef std::set<gfx::NativeView> DockWindows; - - // Enumeration of the ways a drag session can end. - enum EndDragType { - // Drag session exited normally: the user released the mouse. - NORMAL, - - // The drag session was canceled (alt-tab during drag, escape ...) - CANCELED, - - // The tab (NavigationController) was destroyed during the drag. - TAB_DESTROYED - }; - - // Overridden from TabContentsDelegate: - virtual void OpenURLFromTab(TabContents* source, - const GURL& url, - const GURL& referrer, - WindowOpenDisposition disposition, - PageTransition::Type transition); - virtual void NavigationStateChanged(const TabContents* source, - unsigned changed_flags); - virtual void AddNewContents(TabContents* source, - TabContents* new_contents, - WindowOpenDisposition disposition, - const gfx::Rect& initial_pos, - bool user_gesture); - virtual void ActivateContents(TabContents* contents); - virtual void DeactivateContents(TabContents* contents); - virtual void LoadingStateChanged(TabContents* source); - virtual void CloseContents(TabContents* source); - virtual void MoveContents(TabContents* source, const gfx::Rect& pos); - virtual void ToolbarSizeChanged(TabContents* source, bool is_animating); - virtual void URLStarredChanged(TabContents* source, bool starred); - virtual void UpdateTargetURL(TabContents* source, const GURL& url); - - // Overridden from NotificationObserver: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - // Overridden from MessageLoop::Observer: -#if defined(OS_WIN) - virtual void WillProcessMessage(const MSG& msg); - virtual void DidProcessMessage(const MSG& msg); -#else - virtual void WillProcessEvent(GdkEvent* event); - virtual void DidProcessEvent(GdkEvent* event); -#endif - - // Initialize the offset used to calculate the position to create windows - // in |GetWindowCreatePoint|. This should only be invoked from - // |CaptureDragInfo|. - void InitWindowCreatePoint(); - - // Updates the window create point from |mouse_offset_|. - void UpdateWindowCreatePoint(); - - // Returns the point where a detached window should be created given the - // current mouse position. - gfx::Point GetWindowCreatePoint() const; - - void UpdateDockInfo(const gfx::Point& screen_point); - - // Sets the TabContents being dragged with the specified |new_contents|. - void SetDraggedContents(TabContents* new_contents); - - // Saves focus in the window that the drag initiated from. Focus will be - // restored appropriately if the drag ends within this same window. - void SaveFocus(); - - // Restore focus to the View that had focus before the drag was started, if - // the drag ends within the same Window as it began. - void RestoreFocus(); - - // Tests whether the position of the mouse is past a minimum elasticity - // threshold required to start a drag. - bool CanStartDrag() const; - - // Move the DraggedTabView according to the current mouse screen position, - // potentially updating the source and other TabStrips. - void ContinueDragging(); - - // Handles dragging a tab while the tab is attached. - void MoveAttachedTab(const gfx::Point& screen_point); - - // Handles dragging while the tab is detached. - void MoveDetachedTab(const gfx::Point& screen_point); - - // Returns the compatible TabStrip that is under the specified point (screen - // coordinates), or NULL if there is none. - BaseTabStrip* GetTabStripForPoint(const gfx::Point& screen_point); - - DockInfo GetDockInfoAtPoint(const gfx::Point& screen_point); - - // Returns the specified |tabstrip| if it contains the specified point - // (screen coordinates), NULL if it does not. - BaseTabStrip* GetTabStripIfItContains(BaseTabStrip* tabstrip, - const gfx::Point& screen_point) const; - - // Attach the dragged Tab to the specified TabStrip. - void Attach(BaseTabStrip* attached_tabstrip, const gfx::Point& screen_point); - - // Detach the dragged Tab from the current TabStrip. - void Detach(); - - // Returns the index where the dragged TabContents should be inserted into - // the attached TabStripModel given the DraggedTabView's bounds - // |dragged_bounds| in coordinates relative to the attached TabStrip. - // |is_tab_attached| is true if the tab has already been added. - int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds, - bool is_tab_attached) const; - - // Retrieve the bounds of the DraggedTabView, relative to the attached - // TabStrip, given location of the dragged tab in screen coordinates. - gfx::Rect GetDraggedViewTabStripBounds(const gfx::Point& screen_point); - - // Get the position of the dragged tab view relative to the attached tab - // strip. - gfx::Point GetAttachedTabDragPoint(const gfx::Point& screen_point); - - // Finds the Tab within the specified TabStrip that corresponds to the - // dragged TabContents. - BaseTab* GetTabMatchingDraggedContents(BaseTabStrip* tabstrip) const; - - // Does the work for EndDrag. If we actually started a drag and |how_end| is - // not TAB_DESTROYED then one of EndDrag or RevertDrag is invoked. - void EndDragImpl(EndDragType how_end); - - // Reverts a cancelled drag operation. - void RevertDrag(); - - // Finishes a succesful drag operation. - void CompleteDrag(); - - // Create the DraggedTabView, if it does not yet exist. - void EnsureDraggedView(const TabRendererData& data); - - // Utility for getting the mouse position in screen coordinates. - gfx::Point GetCursorScreenPoint() const; - - // Returns the bounds (in screen coordinates) of the specified View. - gfx::Rect GetViewScreenBounds(views::View* tabstrip) const; - - // Utility to convert the specified TabStripModel index to something valid - // for the attached TabStrip. - int NormalizeIndexToAttachedTabStrip(int index) const; - - // Hides the frame for the window that contains the TabStrip the current - // drag session was initiated from. - void HideFrame(); - - // Closes a hidden frame at the end of a drag session. - void CleanUpHiddenFrame(); - - void DockDisplayerDestroyed(DockDisplayer* controller); - - void BringWindowUnderMouseToFront(); - - // Returns the TabStripModel for the specified tabstrip. - TabStripModel* GetModel(BaseTabStrip* tabstrip) const; - - // Handles registering for notifications. - NotificationRegistrar registrar_; - - // The TabContents being dragged. - TabContents* dragged_contents_; - - // The original TabContentsDelegate of |dragged_contents_|, before it was - // detached from the browser window. We store this so that we can forward - // certain delegate notifications back to it if we can't handle them locally. - TabContentsDelegate* original_delegate_; - - // The TabStrip |source_tab_| originated from. - BaseTabStrip* source_tabstrip_; - - // This is the index of the |source_tab_| in |source_tabstrip_| when the drag - // began. This is used to restore the previous state if the drag is aborted. - int source_model_index_; - - // The TabStrip the dragged Tab is currently attached to, or NULL if the - // dragged Tab is detached. - BaseTabStrip* attached_tabstrip_; - - // If attached this is the tab we're dragging. - BaseTab* attached_tab_; - - // The visual representation of the dragged Tab. - scoped_ptr<DraggedTabView> view_; - - // The photo-booth the TabContents sits in when the Tab is detached, to - // obtain screen shots. - scoped_ptr<NativeViewPhotobooth> photobooth_; - - // The position of the mouse (in screen coordinates) at the start of the drag - // operation. This is used to calculate minimum elasticity before a - // DraggedTabView is constructed. - gfx::Point start_screen_point_; - - // This is the offset of the mouse from the top left of the Tab where - // dragging begun. This is used to ensure that the dragged view is always - // positioned at the correct location during the drag, and to ensure that the - // detached window is created at the right location. - gfx::Point mouse_offset_; - - // Ratio of the x-coordinate of the mouse offset to the width of the tab. - float offset_to_width_ratio_; - - // A hint to use when positioning new windows created by detaching Tabs. This - // is the distance of the mouse from the top left of the dragged tab as if it - // were the distance of the mouse from the top left of the first tab in the - // attached TabStrip from the top left of the window. - gfx::Point window_create_point_; - - // Location of the first tab in the source tabstrip in screen coordinates. - // This is used to calculate window_create_point_. - gfx::Point first_source_tab_point_; - - // The bounds of the browser window before the last Tab was detached. When - // the last Tab is detached, rather than destroying the frame (which would - // abort the drag session), the frame is moved off-screen. If the drag is - // aborted (e.g. by the user pressing Esc, or capture being lost), the Tab is - // attached to the hidden frame and the frame moved back to these bounds. - gfx::Rect restore_bounds_; - - // The last view that had focus in the window containing |source_tab_|. This - // is saved so that focus can be restored properly when a drag begins and - // ends within this same window. - views::View* old_focused_view_; - - // The position along the major axis of the mouse cursor in screen coordinates - // at the time of the last re-order event. - int last_move_screen_loc_; - - DockInfo dock_info_; - - DockWindows dock_windows_; - - std::vector<DockDisplayer*> dock_controllers_; - - // Is the tab mini? - const bool mini_; - - // Is the tab pinned? - const bool pinned_; - - // Timer used to bring the window under the cursor to front. If the user - // stops moving the mouse for a brief time over a browser window, it is - // brought to front. - base::OneShotTimer<DraggedTabController> bring_to_front_timer_; - - // Did the mouse move enough that we started a drag? - bool started_drag_; - - // Is the drag active? - bool active_; - - DISALLOW_COPY_AND_ASSIGN(DraggedTabController); -}; +#include "chrome/browser/ui/views/tabs/dragged_tab_controller.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_CONTROLLER_H_ + diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc deleted file mode 100644 index 8f77a87..0000000 --- a/chrome/browser/views/tabs/dragged_tab_view.cc +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/dragged_tab_view.h" - -#include "chrome/browser/views/tabs/native_view_photobooth.h" -#include "gfx/canvas_skia.h" -#include "third_party/skia/include/core/SkShader.h" -#include "views/widget/widget.h" - -#if defined(OS_WIN) -#include "views/widget/widget_win.h" -#elif defined(OS_LINUX) -#include "views/widget/widget_gtk.h" -#endif - -static const int kTransparentAlpha = 200; -static const int kOpaqueAlpha = 255; -static const int kDragFrameBorderSize = 2; -static const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize; -static const float kScalingFactor = 0.5; -static const SkColor kDraggedTabBorderColor = SkColorSetRGB(103, 129, 162); - -//////////////////////////////////////////////////////////////////////////////// -// DraggedTabView, public: - -DraggedTabView::DraggedTabView(views::View* renderer, - const gfx::Point& mouse_tab_offset, - const gfx::Size& contents_size, - const gfx::Size& min_size) - : renderer_(renderer), - show_contents_on_drag_(true), - mouse_tab_offset_(mouse_tab_offset), - tab_size_(min_size), - photobooth_(NULL), - contents_size_(contents_size) { - set_parent_owned(false); - -#if defined(OS_WIN) - container_.reset(new views::WidgetWin); - container_->set_delete_on_destroy(false); - container_->set_window_style(WS_POPUP); - container_->set_window_ex_style( - WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW); - container_->set_can_update_layered_window(false); - container_->Init(NULL, gfx::Rect(0, 0, 0, 0)); - container_->SetContentsView(this); - - BOOL drag; - if ((::SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &drag, 0) != 0) && - (drag == FALSE)) { - show_contents_on_drag_ = false; - } -#else - container_.reset(new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP)); - container_->MakeTransparent(); - container_->set_delete_on_destroy(false); - container_->Init(NULL, gfx::Rect(0, 0, 0, 0)); - container_->SetContentsView(this); -#endif -} - -DraggedTabView::~DraggedTabView() { - GetParent()->RemoveChildView(this); - container_->CloseNow(); -} - -void DraggedTabView::MoveTo(const gfx::Point& screen_point) { - int x; - if (base::i18n::IsRTL()) { - // On RTL locales, a dragged tab (when it is not attached to a tab strip) - // is rendered using a right-to-left orientation so we should calculate the - // window position differently. - gfx::Size ps = GetPreferredSize(); - x = screen_point.x() - ScaleValue(ps.width()) + mouse_tab_offset_.x() + - ScaleValue( - renderer_->MirroredXCoordinateInsideView(mouse_tab_offset_.x())); - } else { - x = screen_point.x() + mouse_tab_offset_.x() - - ScaleValue(mouse_tab_offset_.x()); - } - int y = screen_point.y() + mouse_tab_offset_.y() - - ScaleValue(mouse_tab_offset_.y()); - -#if defined(OS_WIN) - int show_flags = container_->IsVisible() ? SWP_NOZORDER : SWP_SHOWWINDOW; - - container_->SetWindowPos(HWND_TOP, x, y, 0, 0, - SWP_NOSIZE | SWP_NOACTIVATE | show_flags); -#else - gfx::Rect bounds; - container_->GetBounds(&bounds, true); - container_->SetBounds(gfx::Rect(x, y, bounds.width(), bounds.height())); - if (!container_->IsVisible()) - container_->Show(); -#endif -} - -void DraggedTabView::SetTabWidthAndUpdate(int width, - NativeViewPhotobooth* photobooth) { - tab_size_.set_width(width); - photobooth_ = photobooth; -#if defined(OS_WIN) - container_->SetOpacity(kTransparentAlpha); -#endif - ResizeContainer(); - Update(); -} - -void DraggedTabView::Update() { -#if defined(OS_WIN) - container_->set_can_update_layered_window(true); - SchedulePaint(); - container_->PaintNow(gfx::Rect()); - container_->set_can_update_layered_window(false); -#else - SchedulePaint(); -#endif -} - -/////////////////////////////////////////////////////////////////////////////// -// DraggedTabView, views::View overrides: - -void DraggedTabView::Paint(gfx::Canvas* canvas) { - if (show_contents_on_drag_) - PaintDetachedView(canvas); - else - PaintFocusRect(canvas); -} - -void DraggedTabView::Layout() { - int left = 0; - if (base::i18n::IsRTL()) - left = GetPreferredSize().width() - tab_size_.width(); - // The renderer_'s width should be tab_size_.width() in both LTR and RTL - // locales. Wrong width will cause the wrong positioning of the tab view in - // dragging. Please refer to http://crbug.com/6223 for details. - renderer_->SetBounds(left, 0, tab_size_.width(), tab_size_.height()); -} - -gfx::Size DraggedTabView::GetPreferredSize() { - int width = std::max(tab_size_.width(), contents_size_.width()) + - kTwiceDragFrameBorderSize; - int height = tab_size_.height() + kDragFrameBorderSize + - contents_size_.height(); - return gfx::Size(width, height); -} - -//////////////////////////////////////////////////////////////////////////////// -// DraggedTabView, private: - -void DraggedTabView::PaintDetachedView(gfx::Canvas* canvas) { - gfx::Size ps = GetPreferredSize(); - gfx::CanvasSkia scale_canvas(ps.width(), ps.height(), false); - SkBitmap& bitmap_device = const_cast<SkBitmap&>( - scale_canvas.getTopPlatformDevice().accessBitmap(true)); - bitmap_device.eraseARGB(0, 0, 0, 0); - - scale_canvas.FillRectInt(kDraggedTabBorderColor, 0, - tab_size_.height() - kDragFrameBorderSize, - ps.width(), ps.height() - tab_size_.height()); - int image_x = kDragFrameBorderSize; - int image_y = tab_size_.height(); - int image_w = ps.width() - kTwiceDragFrameBorderSize; - int image_h = contents_size_.height(); - scale_canvas.FillRectInt(SK_ColorBLACK, image_x, image_y, image_w, image_h); - photobooth_->PaintScreenshotIntoCanvas( - &scale_canvas, - gfx::Rect(image_x, image_y, image_w, image_h)); - renderer_->ProcessPaint(&scale_canvas); - - SkIRect subset; - subset.set(0, 0, ps.width(), ps.height()); - SkBitmap mipmap = scale_canvas.ExtractBitmap(); - mipmap.buildMipMap(true); - - SkShader* bitmap_shader = - SkShader::CreateBitmapShader(mipmap, SkShader::kClamp_TileMode, - SkShader::kClamp_TileMode); - - SkMatrix shader_scale; - shader_scale.setScale(kScalingFactor, kScalingFactor); - bitmap_shader->setLocalMatrix(shader_scale); - - SkPaint paint; - paint.setShader(bitmap_shader); - paint.setAntiAlias(true); - bitmap_shader->unref(); - - SkRect rc; - rc.fLeft = 0; - rc.fTop = 0; - rc.fRight = SkIntToScalar(ps.width()); - rc.fBottom = SkIntToScalar(ps.height()); - canvas->AsCanvasSkia()->drawRect(rc, paint); -} - -void DraggedTabView::PaintFocusRect(gfx::Canvas* canvas) { - gfx::Size ps = GetPreferredSize(); - canvas->DrawFocusRect(0, 0, - static_cast<int>(ps.width() * kScalingFactor), - static_cast<int>(ps.height() * kScalingFactor)); -} - -void DraggedTabView::ResizeContainer() { - gfx::Size ps = GetPreferredSize(); - int w = ScaleValue(ps.width()); - int h = ScaleValue(ps.height()); -#if defined(OS_WIN) - SetWindowPos(container_->GetNativeView(), HWND_TOPMOST, 0, 0, w, h, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); -#else - gfx::Rect bounds; - container_->GetBounds(&bounds, true); - container_->SetBounds(gfx::Rect(bounds.x(), bounds.y(), w, h)); -#endif -} - -int DraggedTabView::ScaleValue(int value) { - return static_cast<int>(value * kScalingFactor); -} diff --git a/chrome/browser/views/tabs/dragged_tab_view.h b/chrome/browser/views/tabs/dragged_tab_view.h index 0432d46..2848baf 100644 --- a/chrome/browser/views/tabs/dragged_tab_view.h +++ b/chrome/browser/views/tabs/dragged_tab_view.h @@ -6,98 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_VIEW_H_ #pragma once -#include "build/build_config.h" -#include "gfx/point.h" -#include "gfx/size.h" -#include "views/view.h" - -namespace views { -#if defined(OS_WIN) -class WidgetWin; -#elif defined(OS_LINUX) -class WidgetGtk; -#endif -} -namespace gfx { -class Point; -} -class NativeViewPhotobooth; -class Tab; -class TabRenderer; - -class DraggedTabView : public views::View { - public: - // Creates a new DraggedTabView using |renderer| as the View. DraggedTabView - // takes ownership of |renderer|. - DraggedTabView(views::View* renderer, - const gfx::Point& mouse_tab_offset, - const gfx::Size& contents_size, - const gfx::Size& min_size); - virtual ~DraggedTabView(); - - // Moves the DraggedTabView to the appropriate location given the mouse - // pointer at |screen_point|. - void MoveTo(const gfx::Point& screen_point); - - // Sets the offset of the mouse from the upper left corner of the tab. - void set_mouse_tab_offset(const gfx::Point& offset) { - mouse_tab_offset_ = offset; - } - - // Sets the width of the dragged tab and updates the dragged image. - void SetTabWidthAndUpdate(int width, NativeViewPhotobooth* photobooth); - - // Notifies the DraggedTabView that it should update itself. - void Update(); - - private: - // Overridden from views::View: - virtual void Paint(gfx::Canvas* canvas); - virtual void Layout(); - virtual gfx::Size GetPreferredSize(); - - // Paint the view, when it's not attached to any TabStrip. - void PaintDetachedView(gfx::Canvas* canvas); - - // Paint the view, when "Show window contents while dragging" is disabled. - void PaintFocusRect(gfx::Canvas* canvas); - - // Resizes the container to fit the content for the current attachment mode. - void ResizeContainer(); - - // Utility for scaling a size by the current scaling factor. - int ScaleValue(int value); - - // The window that contains the DraggedTabView. -#if defined(OS_WIN) - scoped_ptr<views::WidgetWin> container_; -#elif defined(OS_LINUX) - scoped_ptr<views::WidgetGtk> container_; -#endif - - // The renderer that paints the Tab shape. - scoped_ptr<views::View> renderer_; - - // True if "Show window contents while dragging" is enabled. - bool show_contents_on_drag_; - - // The unscaled offset of the mouse from the top left of the dragged Tab. - // This is used to maintain an appropriate offset for the mouse pointer when - // dragging scaled and unscaled representations, and also to calculate the - // position of detached windows. - gfx::Point mouse_tab_offset_; - - // The size of the tab renderer. - gfx::Size tab_size_; - - // A handle to the DIB containing the current screenshot of the TabContents - // we are dragging. - NativeViewPhotobooth* photobooth_; - - // Size of the TabContents being dragged. - gfx::Size contents_size_; - - DISALLOW_COPY_AND_ASSIGN(DraggedTabView); -}; +#include "chrome/browser/ui/views/tabs/dragged_tab_view.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_DRAGGED_TAB_VIEW_H_ + diff --git a/chrome/browser/views/tabs/native_view_photobooth.h b/chrome/browser/views/tabs/native_view_photobooth.h index 0eba321..1a954e5 100644 --- a/chrome/browser/views/tabs/native_view_photobooth.h +++ b/chrome/browser/views/tabs/native_view_photobooth.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,39 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_ #pragma once -#include "gfx/native_widget_types.h" - -namespace gfx { -class Canvas; -class Rect; -} -/////////////////////////////////////////////////////////////////////////////// -// NativeViewPhotobooth -// -// An object that a NativeView "steps into" to have its picture taken. This is -// used to generate a full size screen shot of the contents of a NativeView -// including any child windows. -// -// Implementation note: This causes the NativeView to be re-parented to a -// mostly off-screen layered window. -// -class NativeViewPhotobooth { - public: - // Creates the photo booth. Constructs a nearly off-screen window, parents - // the view, then shows it. The caller is responsible for destroying this - // photo-booth, since the photo-booth will detach it before it is destroyed. - static NativeViewPhotobooth* Create(gfx::NativeView initial_view); - - // Destroys the photo booth window. - virtual ~NativeViewPhotobooth() {} - - // Replaces the view in the photo booth with the specified one. - virtual void Replace(gfx::NativeView new_view) = 0; - - // Paints the current display image of the window into |canvas|, clipped to - // |target_bounds|. - virtual void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds) = 0; -}; +#include "chrome/browser/ui/views/tabs/native_view_photobooth.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_H_ + diff --git a/chrome/browser/views/tabs/native_view_photobooth_gtk.cc b/chrome/browser/views/tabs/native_view_photobooth_gtk.cc deleted file mode 100644 index a307112..0000000 --- a/chrome/browser/views/tabs/native_view_photobooth_gtk.cc +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/native_view_photobooth_gtk.h" - -#include "base/logging.h" -#include "gfx/canvas.h" - -/////////////////////////////////////////////////////////////////////////////// -// NativeViewPhotoboothGtk, public: - -// static -NativeViewPhotobooth* NativeViewPhotobooth::Create( - gfx::NativeView initial_view) { - return new NativeViewPhotoboothGtk(initial_view); -} - -NativeViewPhotoboothGtk::NativeViewPhotoboothGtk( - gfx::NativeView initial_view) { -} - -NativeViewPhotoboothGtk::~NativeViewPhotoboothGtk() { -} - -void NativeViewPhotoboothGtk::Replace(gfx::NativeView new_view) { - NOTIMPLEMENTED(); -} - -void NativeViewPhotoboothGtk::PaintScreenshotIntoCanvas( - gfx::Canvas* canvas, - const gfx::Rect& target_bounds) { - NOTIMPLEMENTED(); -} diff --git a/chrome/browser/views/tabs/native_view_photobooth_gtk.h b/chrome/browser/views/tabs/native_view_photobooth_gtk.h index 8bc74063..22c3901 100644 --- a/chrome/browser/views/tabs/native_view_photobooth_gtk.h +++ b/chrome/browser/views/tabs/native_view_photobooth_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,25 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_ #pragma once -#include "chrome/browser/views/tabs/native_view_photobooth.h" - -class NativeViewPhotoboothGtk : public NativeViewPhotobooth { - public: - explicit NativeViewPhotoboothGtk(gfx::NativeView new_view); - - // Destroys the photo booth window. - virtual ~NativeViewPhotoboothGtk(); - - // Replaces the view in the photo booth with the specified one. - virtual void Replace(gfx::NativeView new_view); - - // Paints the current display image of the window into |canvas|, clipped to - // |target_bounds|. - virtual void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds); - - private: - DISALLOW_COPY_AND_ASSIGN(NativeViewPhotoboothGtk); -}; +#include "chrome/browser/ui/views/tabs/native_view_photobooth_gtk.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_GTK_H_ + diff --git a/chrome/browser/views/tabs/native_view_photobooth_win.cc b/chrome/browser/views/tabs/native_view_photobooth_win.cc deleted file mode 100644 index d749ea0..0000000 --- a/chrome/browser/views/tabs/native_view_photobooth_win.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/native_view_photobooth_win.h" - -#include "chrome/browser/tab_contents/tab_contents.h" -#include "gfx/canvas_skia.h" -#include "gfx/point.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "views/widget/widget_win.h" - -namespace { - -static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, HDC monitor_dc, - RECT* monitor_rect, LPARAM data) { - gfx::Point* point = reinterpret_cast<gfx::Point*>(data); - if (monitor_rect->right > point->x() && monitor_rect->bottom > point->y()) { - point->set_x(monitor_rect->right); - point->set_y(monitor_rect->bottom); - } - return TRUE; -} - -gfx::Point GetCaptureWindowPosition() { - // Since the capture window must be visible to be painted, it must be opened - // off screen to avoid flashing. But if it is opened completely off-screen - // (e.g. at 0xFFFFx0xFFFF) then on Windows Vista it will not paint even if it - // _is_ visible. So we need to find the right/bottommost monitor, and - // position it so that 1x1 pixel is on-screen on that monitor which is enough - // to convince Vista to paint it. Don't ask why this is so - this appears to - // be a regression over XP. - gfx::Point point(0, 0); - EnumDisplayMonitors(NULL, NULL, &MonitorEnumProc, - reinterpret_cast<LPARAM>(&point)); - return gfx::Point(point.x() - 1, point.y() - 1); -} - -} - -/////////////////////////////////////////////////////////////////////////////// -// NativeViewPhotoboothWin, public: - -// static -NativeViewPhotobooth* NativeViewPhotobooth::Create( - gfx::NativeView initial_view) { - return new NativeViewPhotoboothWin(initial_view); -} - -NativeViewPhotoboothWin::NativeViewPhotoboothWin(HWND initial_hwnd) - : capture_window_(NULL), - current_hwnd_(initial_hwnd) { - DCHECK(IsWindow(current_hwnd_)); - CreateCaptureWindow(initial_hwnd); -} - -NativeViewPhotoboothWin::~NativeViewPhotoboothWin() { - // Detach the attached HWND. The creator of the photo-booth is responsible - // for destroying it. - Replace(NULL); - capture_window_->Close(); -} - -void NativeViewPhotoboothWin::Replace(HWND new_hwnd) { - if (IsWindow(current_hwnd_) && - GetParent(current_hwnd_) == capture_window_->GetNativeView()) { - // We need to hide the window too, so it doesn't show up in the TaskBar or - // be parented to the desktop. - ShowWindow(current_hwnd_, SW_HIDE); - SetParent(current_hwnd_, NULL); - } - current_hwnd_ = new_hwnd; - - if (IsWindow(new_hwnd)) { - // Insert the TabContents into the capture window. - SetParent(current_hwnd_, capture_window_->GetNativeView()); - - // Show the window (it may not be visible). This is the only safe way of - // doing this. ShowWindow does not work. - SetWindowPos(current_hwnd_, NULL, 0, 0, 0, 0, - SWP_DEFERERASE | SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOOWNERZORDER | SWP_NOSENDCHANGING | SWP_NOZORDER | - SWP_SHOWWINDOW | SWP_NOSIZE); - } -} - -void NativeViewPhotoboothWin::PaintScreenshotIntoCanvas( - gfx::Canvas* canvas, - const gfx::Rect& target_bounds) { - // Our contained window may have been re-parented. Make sure it belongs to - // us until someone calls Replace(NULL). - if (IsWindow(current_hwnd_) && - GetParent(current_hwnd_) != capture_window_->GetNativeView()) { - Replace(current_hwnd_); - } - - // We compel the contained HWND to paint now, synchronously. We do this to - // populate the device context with valid and current data. - RedrawWindow(current_hwnd_, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); - - // Transfer the contents of the layered capture window to the screen-shot - // canvas' DIB. - HDC target_dc = canvas->BeginPlatformPaint(); - HDC source_dc = GetDC(current_hwnd_); - RECT window_rect = {0}; - GetWindowRect(current_hwnd_, &window_rect); - BitBlt(target_dc, target_bounds.x(), target_bounds.y(), - target_bounds.width(), target_bounds.height(), source_dc, 0, 0, - SRCCOPY); - // Windows screws up the alpha channel on all text it draws, and so we need - // to call makeOpaque _after_ the blit to correct for this. - canvas->AsCanvasSkia()->getTopPlatformDevice().makeOpaque( - target_bounds.x(), target_bounds.y(), target_bounds.width(), - target_bounds.height()); - ReleaseDC(current_hwnd_, source_dc); - canvas->EndPlatformPaint(); -} - -/////////////////////////////////////////////////////////////////////////////// -// NativeViewPhotoboothWin, private: - -void NativeViewPhotoboothWin::CreateCaptureWindow(HWND initial_hwnd) { - // Snapshotting a HWND is tricky - if the HWND is clipped (e.g. positioned - // partially off-screen) then just blitting from the HWND' DC to the capture - // bitmap would be incorrect, since the capture bitmap would show only the - // visible area of the HWND. - // - // The approach turns out to be to create a second layered window in - // hyperspace the to act as a "photo booth." The window is created with the - // size of the unclipped HWND, and we attach the HWND as a child, refresh the - // HWND' by calling |Paint| on it, and then blitting from the HWND's DC to - // the capture bitmap. This results in the entire unclipped HWND display - // bitmap being captured. - // - // The capture window must be layered so that Windows generates a backing - // store for it, so that blitting from a child window's DC produces data. If - // the window is not layered, because it is off-screen Windows does not - // retain its contents and blitting results in blank data. The capture window - // is a "basic" (1 level of alpha) layered window because that is the mode - // that supports having child windows (variable alpha layered windows do not - // support child HWNDs). - // - // This function sets up the off-screen capture window, and attaches the - // associated HWND to it. Note that the details are important here, see below - // for further comments. - // - CRect contents_rect; - GetClientRect(initial_hwnd, &contents_rect); - gfx::Point window_position = GetCaptureWindowPosition(); - gfx::Rect capture_bounds(window_position.x(), window_position.y(), - contents_rect.Width(), contents_rect.Height()); - capture_window_ = new views::WidgetWin; - capture_window_->set_window_style(WS_POPUP); - // WS_EX_TOOLWINDOW ensures the capture window doesn't produce a Taskbar - // button. - capture_window_->set_window_ex_style(WS_EX_LAYERED | WS_EX_TOOLWINDOW); - capture_window_->Init(NULL, capture_bounds); - // If the capture window isn't visible, blitting from the TabContents' - // HWND's DC to the capture bitmap produces blankness. - capture_window_->Show(); - SetLayeredWindowAttributes( - capture_window_->GetNativeView(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA); - - Replace(initial_hwnd); -} diff --git a/chrome/browser/views/tabs/native_view_photobooth_win.h b/chrome/browser/views/tabs/native_view_photobooth_win.h index 4ed4016..2cd2a4b 100644 --- a/chrome/browser/views/tabs/native_view_photobooth_win.h +++ b/chrome/browser/views/tabs/native_view_photobooth_win.h @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,53 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_ #pragma once -#include "chrome/browser/views/tabs/native_view_photobooth.h" - -namespace views { -class WidgetWin; -} - -/////////////////////////////////////////////////////////////////////////////// -// HWNDPhotobooth -// -// An object that a HWND "steps into" to have its picture taken. This is used -// to generate a full size screen shot of the contents of a HWND including -// any child windows. -// -// Implementation note: This causes the HWND to be re-parented to a mostly -// off-screen layered window. -// -class NativeViewPhotoboothWin : public NativeViewPhotobooth { - public: - // Creates the photo booth. Constructs a nearly off-screen window, parents - // the HWND, then shows it. The caller is responsible for destroying this - // window, since the photo-booth will detach it before it is destroyed. - // |canvas| is a canvas to paint the contents into, and dest_bounds is the - // target area in |canvas| to which painted contents will be clipped. - explicit NativeViewPhotoboothWin(gfx::NativeView initial_view); - - // Destroys the photo booth window. - virtual ~NativeViewPhotoboothWin(); - - // Replaces the view in the photo booth with the specified one. - virtual void Replace(gfx::NativeView new_view); - - // Paints the current display image of the window into |canvas|, clipped to - // |target_bounds|. - virtual void PaintScreenshotIntoCanvas(gfx::Canvas* canvas, - const gfx::Rect& target_bounds); - - private: - // Creates a mostly off-screen window to contain the HWND to be captured. - void CreateCaptureWindow(HWND initial_hwnd); - - // The nearly off-screen photo-booth layered window used to hold the HWND. - views::WidgetWin* capture_window_; - - // The current HWND being captured. - HWND current_hwnd_; - - DISALLOW_COPY_AND_ASSIGN(NativeViewPhotoboothWin); -}; +#include "chrome/browser/ui/views/tabs/native_view_photobooth_win.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_NATIVE_VIEW_PHOTOBOOTH_WIN_H_ + diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc deleted file mode 100644 index b42bca0..0000000 --- a/chrome/browser/views/tabs/side_tab.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/side_tab.h" - -#include "app/resource_bundle.h" -#include "base/utf_string_conversions.h" -#include "gfx/canvas_skia.h" -#include "gfx/favicon_size.h" -#include "gfx/path.h" -#include "gfx/skia_util.h" -#include "grit/app_resources.h" -#include "grit/theme_resources.h" -#include "views/controls/button/image_button.h" - -namespace { -const int kVerticalTabHeight = 27; -const int kTitleCloseSpacing = 4; -const SkScalar kRoundRectRadius = 4; -const SkColor kTabBackgroundColor = SK_ColorWHITE; -const SkColor kTextColor = SK_ColorBLACK; - -// Padding between the edge and the icon. -const int kIconLeftPadding = 5; - -// Location the title starts at. -const int kTitleX = kIconLeftPadding + kFavIconSize + 5; -}; - -//////////////////////////////////////////////////////////////////////////////// -// SideTab, public: - -SideTab::SideTab(TabController* controller) - : BaseTab(controller) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - close_button()->SetBackground(kTextColor, - rb.GetBitmapNamed(IDR_TAB_CLOSE), - rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK)); -} - -SideTab::~SideTab() { -} - -// static -int SideTab::GetPreferredHeight() { - return 27; -} - -//////////////////////////////////////////////////////////////////////////////// -// SideTab, views::View overrides: - -void SideTab::Layout() { - if (ShouldShowIcon()) { - int icon_x = kIconLeftPadding; - int icon_y = (height() - kFavIconSize) / 2; - int icon_size = - !data().favicon.empty() ? data().favicon.width() : kFavIconSize; - if (icon_size != kFavIconSize) { - icon_x -= (icon_size - kFavIconSize) / 2; - icon_y -= (icon_size - kFavIconSize) / 2; - } - icon_bounds_.SetRect(icon_x, icon_y, icon_size, icon_size); - } else { - icon_bounds_ = gfx::Rect(); - } - - gfx::Size ps = close_button()->GetPreferredSize(); - int close_y = (height() - ps.height()) / 2; - close_button()->SetBounds( - std::max(0, width() - ps.width() - - (GetPreferredHeight() - ps.height()) / 2), - close_y, - ps.width(), - ps.height()); - - int title_y = (height() - font_height()) / 2; - title_bounds_.SetRect( - kTitleX, - title_y, - std::max(0, close_button()->x() - kTitleCloseSpacing - kTitleX), - font_height()); -} - -void SideTab::Paint(gfx::Canvas* canvas) { - if (ShouldPaintHighlight()) { - SkPaint paint; - paint.setColor(kTabBackgroundColor); - paint.setAntiAlias(true); - SkRect border_rect = { SkIntToScalar(0), SkIntToScalar(0), - SkIntToScalar(width()), SkIntToScalar(height()) }; - canvas->AsCanvasSkia()->drawRoundRect(border_rect, - SkIntToScalar(kRoundRectRadius), - SkIntToScalar(kRoundRectRadius), - paint); - } - - if (ShouldShowIcon()) - PaintIcon(canvas, icon_bounds_.x(), icon_bounds_.y()); - - PaintTitle(canvas, kTextColor); -} - -gfx::Size SideTab::GetPreferredSize() { - return gfx::Size(0, GetPreferredHeight()); -} - -bool SideTab::ShouldPaintHighlight() const { - return IsSelected() || !controller(); -} - -bool SideTab::ShouldShowIcon() const { - return data().mini || data().show_icon; -} diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h index 6cff764..5d27ce3 100644 --- a/chrome/browser/views/tabs/side_tab.h +++ b/chrome/browser/views/tabs/side_tab.h @@ -6,39 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_ #pragma once -#include "chrome/browser/views/tabs/base_tab.h" -#include "gfx/font.h" - -class SideTab; -class TabStripController; - -class SideTab : public BaseTab { - public: - explicit SideTab(TabController* controller); - virtual ~SideTab(); - - // Returns the preferred height of side tabs. - static int GetPreferredHeight(); - - // views::View Overrides: - virtual void Layout(); - virtual void Paint(gfx::Canvas* canvas); - virtual gfx::Size GetPreferredSize(); - - protected: - virtual const gfx::Rect& title_bounds() const { return title_bounds_; } - - // Returns true if the selected highlight should be rendered. - virtual bool ShouldPaintHighlight() const; - - private: - // Returns true if the icon should be shown. - bool ShouldShowIcon() const; - - gfx::Rect icon_bounds_; - gfx::Rect title_bounds_; - - DISALLOW_COPY_AND_ASSIGN(SideTab); -}; +#include "chrome/browser/ui/views/tabs/side_tab.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_H_ + diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc deleted file mode 100644 index 84e8082..0000000 --- a/chrome/browser/views/tabs/side_tab_strip.cc +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/side_tab_strip.h" - -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "chrome/browser/views/tabs/side_tab.h" -#include "chrome/browser/views/tabs/tab_strip_controller.h" -#include "chrome/browser/view_ids.h" -#include "gfx/canvas.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "views/background.h" -#include "views/controls/button/image_button.h" - -namespace { -const int kVerticalTabSpacing = 2; -const int kTabStripWidth = 140; -const SkColor kBackgroundColor = SkColorSetARGB(255, 209, 220, 248); -const SkColor kSeparatorColor = SkColorSetARGB(255, 151, 159, 179); - -// Height of the separator. -const int kSeparatorHeight = 1; - -// The new tab button is rendered using a SideTab. -class SideTabNewTabButton : public SideTab { - public: - explicit SideTabNewTabButton(TabStripController* controller); - - virtual bool ShouldPaintHighlight() const { return false; } - virtual bool IsSelected() const { return false; } - bool OnMousePressed(const views::MouseEvent& event); - void OnMouseReleased(const views::MouseEvent& event, bool canceled); - - private: - TabStripController* controller_; - - DISALLOW_COPY_AND_ASSIGN(SideTabNewTabButton); -}; - -SideTabNewTabButton::SideTabNewTabButton(TabStripController* controller) - : SideTab(NULL), - controller_(controller) { - // Never show a close button for the new tab button. - close_button()->SetVisible(false); - TabRendererData data; - data.favicon = *ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_SIDETABS_NEW_TAB); - data.title = l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE); - SetData(data); -} - -bool SideTabNewTabButton::OnMousePressed(const views::MouseEvent& event) { - return true; -} - -void SideTabNewTabButton::OnMouseReleased(const views::MouseEvent& event, - bool canceled) { - if (!canceled && event.IsOnlyLeftMouseButton() && HitTest(event.location())) - controller_->CreateNewTab(); -} - -} // namespace - -// static -const int SideTabStrip::kTabStripInset = 3; - -//////////////////////////////////////////////////////////////////////////////// -// SideTabStrip, public: - -SideTabStrip::SideTabStrip(TabStripController* controller) - : BaseTabStrip(controller, BaseTabStrip::VERTICAL_TAB_STRIP), - newtab_button_(new SideTabNewTabButton(controller)), - separator_(new views::View()) { - SetID(VIEW_ID_TAB_STRIP); - set_background(views::Background::CreateSolidBackground(kBackgroundColor)); - AddChildView(newtab_button_); - separator_->set_background( - views::Background::CreateSolidBackground(kSeparatorColor)); - AddChildView(separator_); -} - -SideTabStrip::~SideTabStrip() { - DestroyDragController(); -} - -//////////////////////////////////////////////////////////////////////////////// -// SideTabStrip, BaseTabStrip implementation: - -int SideTabStrip::GetPreferredHeight() { - return 0; -} - -void SideTabStrip::SetBackgroundOffset(const gfx::Point& offset) { -} - -bool SideTabStrip::IsPositionInWindowCaption(const gfx::Point& point) { - return GetViewForPoint(point) == this; -} - -void SideTabStrip::SetDraggedTabBounds(int tab_index, - const gfx::Rect& tab_bounds) { -} - -TabStrip* SideTabStrip::AsTabStrip() { - return NULL; -} - -void SideTabStrip::StartHighlight(int model_index) { -} - -void SideTabStrip::StopAllHighlighting() { -} - -BaseTab* SideTabStrip::CreateTabForDragging() { - SideTab* tab = new SideTab(NULL); - // Make sure the dragged tab shares our theme provider. We need to explicitly - // do this as during dragging there isn't a theme provider. - tab->set_theme_provider(GetThemeProvider()); - return tab; -} - -void SideTabStrip::RemoveTabAt(int model_index) { - StartRemoveTabAnimation(model_index); -} - -void SideTabStrip::SelectTabAt(int old_model_index, int new_model_index) { - GetBaseTabAtModelIndex(new_model_index)->SchedulePaint(); -} - -void SideTabStrip::TabTitleChangedNotLoading(int model_index) { -} - -gfx::Size SideTabStrip::GetPreferredSize() { - return gfx::Size(kTabStripWidth, 0); -} - -void SideTabStrip::PaintChildren(gfx::Canvas* canvas) { - // Make sure the dragged tab appears on top of all others by paint it last. - BaseTab* dragging_tab = NULL; - - // Paint the new tab and separator first so that any tabs animating appear on - // top. - separator_->ProcessPaint(canvas); - newtab_button_->ProcessPaint(canvas); - - for (int i = tab_count() - 1; i >= 0; --i) { - BaseTab* tab = base_tab_at_tab_index(i); - if (tab->dragging()) - dragging_tab = tab; - else - tab->ProcessPaint(canvas); - } - - if (dragging_tab) - dragging_tab->ProcessPaint(canvas); -} - -BaseTab* SideTabStrip::CreateTab() { - return new SideTab(this); -} - -void SideTabStrip::GenerateIdealBounds() { - gfx::Rect layout_rect = GetLocalBounds(false); - layout_rect.Inset(kTabStripInset, kTabStripInset); - - int y = layout_rect.y(); - bool last_was_mini = true; - bool has_non_closing_tab = false; - separator_bounds_.SetRect(0, -kSeparatorHeight, width(), kSeparatorHeight); - for (int i = 0; i < tab_count(); ++i) { - BaseTab* tab = base_tab_at_tab_index(i); - if (!tab->closing()) { - if (last_was_mini != tab->data().mini) { - if (has_non_closing_tab) { - separator_bounds_.SetRect(0, y, width(), kSeparatorHeight); - y += kSeparatorHeight + kVerticalTabSpacing; - } - newtab_button_bounds_.SetRect( - layout_rect.x(), y, layout_rect.width(), - newtab_button_->GetPreferredSize().height()); - y = newtab_button_bounds_.bottom() + kVerticalTabSpacing; - last_was_mini = tab->data().mini; - } - gfx::Rect bounds = gfx::Rect(layout_rect.x(), y, layout_rect.width(), - tab->GetPreferredSize().height()); - set_ideal_bounds(i, bounds); - y = bounds.bottom() + kVerticalTabSpacing; - has_non_closing_tab = true; - } - } - - if (last_was_mini) { - if (has_non_closing_tab) { - separator_bounds_.SetRect(0, y, width(), kSeparatorHeight); - y += kSeparatorHeight + kVerticalTabSpacing; - } - newtab_button_bounds_ = - gfx::Rect(layout_rect.x(), y, layout_rect.width(), - newtab_button_->GetPreferredSize().height()); - } -} - -void SideTabStrip::StartInsertTabAnimation(int model_index, bool foreground) { - PrepareForAnimation(); - - GenerateIdealBounds(); - - int tab_data_index = ModelIndexToTabIndex(model_index); - BaseTab* tab = base_tab_at_tab_index(tab_data_index); - if (model_index == 0) { - tab->SetBounds(ideal_bounds(tab_data_index).x(), 0, - ideal_bounds(tab_data_index).width(), 0); - } else { - BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1); - tab->SetBounds(last_tab->x(), last_tab->bounds().bottom(), - ideal_bounds(tab_data_index).width(), 0); - } - - AnimateToIdealBounds(); -} - -void SideTabStrip::StartMoveTabAnimation() { - PrepareForAnimation(); - - GenerateIdealBounds(); - AnimateToIdealBounds(); -} - -void SideTabStrip::StopAnimating(bool layout) { - if (!IsAnimating()) - return; - - bounds_animator().Cancel(); - - if (layout) - DoLayout(); -} - -void SideTabStrip::AnimateToIdealBounds() { - for (int i = 0; i < tab_count(); ++i) { - BaseTab* tab = base_tab_at_tab_index(i); - if (!tab->closing() && !tab->dragging()) - bounds_animator().AnimateViewTo(tab, ideal_bounds(i)); - } - - bounds_animator().AnimateViewTo(newtab_button_, newtab_button_bounds_); - - bounds_animator().AnimateViewTo(separator_, separator_bounds_); -} - -void SideTabStrip::DoLayout() { - BaseTabStrip::DoLayout(); - - newtab_button_->SetBounds(newtab_button_bounds_); - - separator_->SetBounds(separator_bounds_); -} diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h index c847077..cbecf20 100644 --- a/chrome/browser/views/tabs/side_tab_strip.h +++ b/chrome/browser/views/tabs/side_tab_strip.h @@ -6,62 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_H_ #pragma once -#include "chrome/browser/views/tabs/base_tab_strip.h" - -struct TabRendererData; - -class SideTabStrip : public BaseTabStrip { - public: - // The tabs are inset by this much along all axis. - static const int kTabStripInset; - - explicit SideTabStrip(TabStripController* controller); - virtual ~SideTabStrip(); - - // BaseTabStrip implementation: - virtual int GetPreferredHeight(); - virtual void SetBackgroundOffset(const gfx::Point& offset); - virtual bool IsPositionInWindowCaption(const gfx::Point& point); - virtual void SetDraggedTabBounds(int tab_index, - const gfx::Rect& tab_bounds); - virtual TabStrip* AsTabStrip(); - - virtual void StartHighlight(int model_index); - virtual void StopAllHighlighting(); - virtual BaseTab* CreateTabForDragging(); - virtual void RemoveTabAt(int model_index); - virtual void SelectTabAt(int old_model_index, int new_model_index); - virtual void TabTitleChangedNotLoading(int model_index); - - // views::View overrides: - virtual gfx::Size GetPreferredSize(); - virtual void PaintChildren(gfx::Canvas* canvas); - - protected: - // BaseTabStrip overrides: - virtual BaseTab* CreateTab(); - virtual void GenerateIdealBounds(); - virtual void StartInsertTabAnimation(int model_index, bool foreground); - virtual void StartMoveTabAnimation(); - virtual void StopAnimating(bool layout); - virtual void AnimateToIdealBounds(); - virtual void DoLayout(); - - private: - // The "New Tab" button. - views::View* newtab_button_; - - // Ideal bounds of the new tab button. - gfx::Rect newtab_button_bounds_; - - // Separator between mini-tabs and the new tab button. The separator is - // positioned above the visible area if there are no mini-tabs. - views::View* separator_; - - // Bounds of the sepatator. - gfx::Rect separator_bounds_; - - DISALLOW_COPY_AND_ASSIGN(SideTabStrip); -}; +#include "chrome/browser/ui/views/tabs/side_tab_strip.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_H_ + diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc deleted file mode 100644 index dda22fb..0000000 --- a/chrome/browser/views/tabs/tab.cc +++ /dev/null @@ -1,610 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/tab.h" - -#include <limits> - -#include "app/multi_animation.h" -#include "app/resource_bundle.h" -#include "app/slide_animation.h" -#include "app/throb_animation.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/defaults.h" -#include "chrome/browser/themes/browser_theme_provider.h" -#include "gfx/canvas_skia.h" -#include "gfx/favicon_size.h" -#include "gfx/font.h" -#include "gfx/path.h" -#include "gfx/skbitmap_operations.h" -#include "grit/app_resources.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "views/controls/button/image_button.h" -#include "views/widget/tooltip_manager.h" -#include "views/widget/widget.h" -#include "views/window/non_client_view.h" -#include "views/window/window.h" - -static const int kLeftPadding = 16; -static const int kTopPadding = 6; -static const int kRightPadding = 15; -static const int kBottomPadding = 5; -static const int kDropShadowHeight = 2; -static const int kToolbarOverlap = 1; -static const int kFavIconTitleSpacing = 4; -static const int kTitleCloseButtonSpacing = 5; -static const int kStandardTitleWidth = 175; -static const int kCloseButtonVertFuzz = 0; -static const int kCloseButtonHorzFuzz = 5; - -// Vertical adjustment to the favicon when the tab has a large icon. -static const int kAppTapFaviconVerticalAdjustment = 2; - -// When a non-mini-tab becomes a mini-tab the width of the tab animates. If -// the width of a mini-tab is >= kMiniTabRendererAsNormalTabWidth then the tab -// is rendered as a normal tab. This is done to avoid having the title -// immediately disappear when transitioning a tab from normal to mini-tab. -static const int kMiniTabRendererAsNormalTabWidth = - browser_defaults::kMiniTabWidth + 30; - -// How opaque to make the hover state (out of 1). -static const double kHoverOpacity = 0.33; - -Tab::TabImage Tab::tab_alpha = {0}; -Tab::TabImage Tab::tab_active = {0}; -Tab::TabImage Tab::tab_inactive = {0}; - -// Durations for the various parts of the mini tab title animation. -static const int kMiniTitleChangeAnimationDuration1MS = 1600; -static const int kMiniTitleChangeAnimationStart1MS = 0; -static const int kMiniTitleChangeAnimationEnd1MS = 1900; -static const int kMiniTitleChangeAnimationDuration2MS = 0; -static const int kMiniTitleChangeAnimationDuration3MS = 550; -static const int kMiniTitleChangeAnimationStart3MS = 150; -static const int kMiniTitleChangeAnimationEnd3MS = 800; - -// Offset from the right edge for the start of the mini title change animation. -static const int kMiniTitleChangeInitialXOffset = 6; - -// Radius of the radial gradient used for mini title change animation. -static const int kMiniTitleChangeGradientRadius = 20; - -// Colors of the gradient used during the mini title change animation. -static const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE; -static const SkColor kMiniTitleChangeGradientColor2 = - SkColorSetARGB(0, 255, 255, 255); - -// Hit mask constants. -static const SkScalar kTabCapWidth = 15; -static const SkScalar kTabTopCurveWidth = 4; -static const SkScalar kTabBottomCurveWidth = 3; - -namespace { - -void InitTabResources() { - static bool initialized = false; - if (initialized) - return; - - initialized = true; - Tab::LoadTabImages(); -} - -} // namespace - -// static -const char Tab::kViewClassName[] = "browser/tabs/Tab"; - -//////////////////////////////////////////////////////////////////////////////// -// Tab, public: - -Tab::Tab(TabController* controller) - : BaseTab(controller), - showing_icon_(false), - showing_close_button_(false), - close_button_color_(NULL) { - InitTabResources(); -} - -Tab::~Tab() { -} - -void Tab::StartMiniTabTitleAnimation() { - if (!mini_title_animation_.get()) { - MultiAnimation::Parts parts; - parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration1MS, - Tween::EASE_OUT)); - parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration2MS, - Tween::ZERO)); - parts.push_back(MultiAnimation::Part(kMiniTitleChangeAnimationDuration3MS, - Tween::EASE_IN)); - parts[0].start_time_ms = kMiniTitleChangeAnimationStart1MS; - parts[0].end_time_ms = kMiniTitleChangeAnimationEnd1MS; - parts[2].start_time_ms = kMiniTitleChangeAnimationStart3MS; - parts[2].end_time_ms = kMiniTitleChangeAnimationEnd3MS; - mini_title_animation_.reset(new MultiAnimation(parts)); - mini_title_animation_->SetContainer(animation_container()); - mini_title_animation_->set_delegate(this); - } - mini_title_animation_->Start(); -} - -void Tab::StopMiniTabTitleAnimation() { - if (mini_title_animation_.get()) - mini_title_animation_->Stop(); -} - -void Tab::PaintIcon(gfx::Canvas* canvas) { - BaseTab::PaintIcon(canvas, favicon_bounds_.x(), favicon_bounds_.y()); -} - -// static -gfx::Size Tab::GetMinimumUnselectedSize() { - InitTabResources(); - - gfx::Size minimum_size; - minimum_size.set_width(kLeftPadding + kRightPadding); - // Since we use bitmap images, the real minimum height of the image is - // defined most accurately by the height of the end cap images. - minimum_size.set_height(tab_active.image_l->height()); - return minimum_size; -} - -// static -gfx::Size Tab::GetMinimumSelectedSize() { - gfx::Size minimum_size = GetMinimumUnselectedSize(); - minimum_size.set_width(kLeftPadding + kFavIconSize + kRightPadding); - return minimum_size; -} - -// static -gfx::Size Tab::GetStandardSize() { - gfx::Size standard_size = GetMinimumUnselectedSize(); - standard_size.set_width( - standard_size.width() + kFavIconTitleSpacing + kStandardTitleWidth); - return standard_size; -} - -// static -int Tab::GetMiniWidth() { - return browser_defaults::kMiniTabWidth; -} - -//////////////////////////////////////////////////////////////////////////////// -// Tab, protected: - -void Tab::DataChanged(const TabRendererData& old) { - if (data().blocked == old.blocked) - return; - - if (data().blocked) - StartPulse(); - else - StopPulse(); -} - -//////////////////////////////////////////////////////////////////////////////// -// Tab, views::View overrides: - -void Tab::Paint(gfx::Canvas* canvas) { - // Don't paint if we're narrower than we can render correctly. (This should - // only happen during animations). - if (width() < GetMinimumUnselectedSize().width() && !data().mini) - return; - - // See if the model changes whether the icons should be painted. - const bool show_icon = ShouldShowIcon(); - const bool show_close_button = ShouldShowCloseBox(); - if (show_icon != showing_icon_ || show_close_button != showing_close_button_) - Layout(); - - PaintTabBackground(canvas); - - SkColor title_color = GetThemeProvider()-> - GetColor(IsSelected() ? - BrowserThemeProvider::COLOR_TAB_TEXT : - BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT); - - if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth) - PaintTitle(canvas, title_color); - - if (show_icon) - PaintIcon(canvas); - - // If the close button color has changed, generate a new one. - if (!close_button_color_ || title_color != close_button_color_) { - close_button_color_ = title_color; - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - close_button()->SetBackground(close_button_color_, - rb.GetBitmapNamed(IDR_TAB_CLOSE), - rb.GetBitmapNamed(IDR_TAB_CLOSE_MASK)); - } -} - -void Tab::Layout() { - gfx::Rect lb = GetLocalBounds(false); - if (lb.IsEmpty()) - return; - lb.Inset(kLeftPadding, kTopPadding, kRightPadding, kBottomPadding); - - // The height of the content of the Tab is the largest of the favicon, - // the title text and the close button graphic. - int content_height = std::max(kFavIconSize, font_height()); - gfx::Size close_button_size(close_button()->GetPreferredSize()); - content_height = std::max(content_height, close_button_size.height()); - - // Size the Favicon. - showing_icon_ = ShouldShowIcon(); - if (showing_icon_) { - // Use the size of the favicon as apps use a bigger favicon size. - int favicon_size = - !data().favicon.empty() ? data().favicon.width() : kFavIconSize; - int favicon_top = kTopPadding + content_height / 2 - favicon_size / 2; - int favicon_left = lb.x(); - if (favicon_size != kFavIconSize) { - favicon_left -= (favicon_size - kFavIconSize) / 2; - favicon_top -= kAppTapFaviconVerticalAdjustment; - } - favicon_bounds_.SetRect(favicon_left, favicon_top, - favicon_size, favicon_size); - if (data().mini && width() < kMiniTabRendererAsNormalTabWidth) { - // Adjust the location of the favicon when transitioning from a normal - // tab to a mini-tab. - int mini_delta = kMiniTabRendererAsNormalTabWidth - GetMiniWidth(); - int ideal_delta = width() - GetMiniWidth(); - if (ideal_delta < mini_delta) { - int ideal_x = (GetMiniWidth() - favicon_size) / 2; - int x = favicon_bounds_.x() + static_cast<int>( - (1 - static_cast<float>(ideal_delta) / - static_cast<float>(mini_delta)) * - (ideal_x - favicon_bounds_.x())); - favicon_bounds_.set_x(x); - } - } - } else { - favicon_bounds_.SetRect(lb.x(), lb.y(), 0, 0); - } - - // Size the Close button. - showing_close_button_ = ShouldShowCloseBox(); - if (showing_close_button_) { - int close_button_top = kTopPadding + kCloseButtonVertFuzz + - (content_height - close_button_size.height()) / 2; - // If the ratio of the close button size to tab width exceeds the maximum. - close_button()->SetBounds(lb.width() + kCloseButtonHorzFuzz, - close_button_top, close_button_size.width(), - close_button_size.height()); - close_button()->SetVisible(true); - } else { - close_button()->SetBounds(0, 0, 0, 0); - close_button()->SetVisible(false); - } - - int title_left = favicon_bounds_.right() + kFavIconTitleSpacing; - int title_top = kTopPadding + (content_height - font_height()) / 2; - // Size the Title text to fill the remaining space. - if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) { - // If the user has big fonts, the title will appear rendered too far down - // on the y-axis if we use the regular top padding, so we need to adjust it - // so that the text appears centered. - gfx::Size minimum_size = GetMinimumUnselectedSize(); - int text_height = title_top + font_height() + kBottomPadding; - if (text_height > minimum_size.height()) - title_top -= (text_height - minimum_size.height()) / 2; - - int title_width; - if (close_button()->IsVisible()) { - title_width = std::max(close_button()->x() - - kTitleCloseButtonSpacing - title_left, 0); - } else { - title_width = std::max(lb.width() - title_left, 0); - } - title_bounds_.SetRect(title_left, title_top, title_width, font_height()); - } else { - title_bounds_.SetRect(title_left, title_top, 0, 0); - } - - // Certain UI elements within the Tab (the favicon, etc.) are not represented - // as child Views (which is the preferred method). Instead, these UI elements - // are drawn directly on the canvas from within Tab::Paint(). The Tab's child - // Views (for example, the Tab's close button which is a views::Button - // instance) are automatically mirrored by the mirroring infrastructure in - // views. The elements Tab draws directly on the canvas need to be manually - // mirrored if the View's layout is right-to-left. - title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_)); -} - -void Tab::OnThemeChanged() { - Tab::LoadTabImages(); -} - -bool Tab::HasHitTestMask() const { - return true; -} - -void Tab::GetHitTestMask(gfx::Path* path) const { - DCHECK(path); - - SkScalar h = SkIntToScalar(height()); - SkScalar w = SkIntToScalar(width()); - - path->moveTo(0, h); - - // Left end cap. - path->lineTo(kTabBottomCurveWidth, h - kTabBottomCurveWidth); - path->lineTo(kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth); - path->lineTo(kTabCapWidth, 0); - - // Connect to the right cap. - path->lineTo(w - kTabCapWidth, 0); - - // Right end cap. - path->lineTo(w - kTabCapWidth + kTabTopCurveWidth, kTabTopCurveWidth); - path->lineTo(w - kTabBottomCurveWidth, h - kTabBottomCurveWidth); - path->lineTo(w, h); - - // Close out the path. - path->lineTo(0, h); - path->close(); -} - -bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) { - origin->set_x(title_bounds().x() + 10); - origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4); - return true; -} - -//////////////////////////////////////////////////////////////////////////////// -// Tab, private - -void Tab::PaintTabBackground(gfx::Canvas* canvas) { - if (IsSelected()) { - PaintActiveTabBackground(canvas); - } else { - if (mini_title_animation_.get() && mini_title_animation_->is_animating()) - PaintInactiveTabBackgroundWithTitleChange(canvas); - else - PaintInactiveTabBackground(canvas); - - double throb_value = GetThrobValue(); - if (throb_value > 0) { - canvas->SaveLayerAlpha(static_cast<int>(throb_value * 0xff), - gfx::Rect(width(), height())); - canvas->AsCanvasSkia()->drawARGB(0, 255, 255, 255, - SkXfermode::kClear_Mode); - PaintActiveTabBackground(canvas); - canvas->Restore(); - } - } -} - -void Tab::PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas) { - // Render the inactive tab background. We'll use this for clipping. - gfx::CanvasSkia background_canvas(width(), height(), false); - PaintInactiveTabBackground(&background_canvas); - - SkBitmap background_image = background_canvas.ExtractBitmap(); - - // Draw a radial gradient to hover_canvas. - gfx::CanvasSkia hover_canvas(width(), height(), false); - int radius = kMiniTitleChangeGradientRadius; - int x0 = width() + radius - kMiniTitleChangeInitialXOffset; - int x1 = radius; - int x2 = -radius; - int x; - if (mini_title_animation_->current_part_index() == 0) { - x = mini_title_animation_->CurrentValueBetween(x0, x1); - } else if (mini_title_animation_->current_part_index() == 1) { - x = x1; - } else { - x = mini_title_animation_->CurrentValueBetween(x1, x2); - } - SkPaint paint; - SkPoint loc = { SkIntToScalar(x), SkIntToScalar(0) }; - SkColor colors[2]; - colors[0] = kMiniTitleChangeGradientColor1; - colors[1] = kMiniTitleChangeGradientColor2; - SkShader* shader = SkGradientShader::CreateRadial( - loc, - SkIntToScalar(radius), - colors, - NULL, - 2, - SkShader::kClamp_TileMode); - paint.setShader(shader); - shader->unref(); - hover_canvas.DrawRectInt(x - radius, -radius, radius * 2, radius * 2, paint); - - // Draw the radial gradient clipped to the background into hover_image. - SkBitmap hover_image = SkBitmapOperations::CreateMaskedBitmap( - hover_canvas.ExtractBitmap(), background_image); - - // Draw the tab background to the canvas. - canvas->DrawBitmapInt(background_image, 0, 0); - - // And then the gradient on top of that. - if (mini_title_animation_->current_part_index() == 2) { - canvas->SaveLayerAlpha(mini_title_animation_->CurrentValueBetween(255, 0)); - canvas->DrawBitmapInt(hover_image, 0, 0); - canvas->Restore(); - } else { - canvas->DrawBitmapInt(hover_image, 0, 0); - } -} - -void Tab::PaintInactiveTabBackground(gfx::Canvas* canvas) { - bool is_otr = data().off_the_record; - - // The tab image needs to be lined up with the background image - // so that it feels partially transparent. These offsets represent the tab - // position within the frame background image. - int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) + - background_offset_.x(); - - int tab_id; - if (GetWidget() && - GetWidget()->GetWindow()->GetNonClientView()->UseNativeFrame()) { - tab_id = IDR_THEME_TAB_BACKGROUND_V; - } else { - tab_id = is_otr ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : - IDR_THEME_TAB_BACKGROUND; - } - - SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(tab_id); - - TabImage* tab_image = &tab_active; - TabImage* tab_inactive_image = &tab_inactive; - TabImage* alpha = &tab_alpha; - - // If the theme is providing a custom background image, then its top edge - // should be at the top of the tab. Otherwise, we assume that the background - // image is a composited foreground + frame image. - int bg_offset_y = GetThemeProvider()->HasCustomImage(tab_id) ? - 0 : background_offset_.y(); - - // Draw left edge. Don't draw over the toolbar, as we're not the foreground - // tab. - SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap( - *tab_bg, offset, bg_offset_y, tab_image->l_width, height()); - SkBitmap theme_l = - SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l); - canvas->DrawBitmapInt(theme_l, - 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, - 0, 0, theme_l.width(), theme_l.height() - kToolbarOverlap, - false); - - // Draw right edge. Again, don't draw over the toolbar. - SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg, - offset + width() - tab_image->r_width, bg_offset_y, - tab_image->r_width, height()); - SkBitmap theme_r = - SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r); - canvas->DrawBitmapInt(theme_r, - 0, 0, theme_r.width(), theme_r.height() - kToolbarOverlap, - width() - theme_r.width(), 0, theme_r.width(), - theme_r.height() - kToolbarOverlap, false); - - // Draw center. Instead of masking out the top portion we simply skip over - // it by incrementing by kDropShadowHeight, since it's a simple rectangle. - // And again, don't draw over the toolbar. - canvas->TileImageInt(*tab_bg, - offset + tab_image->l_width, - bg_offset_y + kDropShadowHeight + tab_image->y_offset, - tab_image->l_width, - kDropShadowHeight + tab_image->y_offset, - width() - tab_image->l_width - tab_image->r_width, - height() - kDropShadowHeight - kToolbarOverlap - tab_image->y_offset); - - // Now draw the highlights/shadows around the tab edge. - canvas->DrawBitmapInt(*tab_inactive_image->image_l, 0, 0); - canvas->TileImageInt(*tab_inactive_image->image_c, - tab_inactive_image->l_width, 0, - width() - tab_inactive_image->l_width - - tab_inactive_image->r_width, - height()); - canvas->DrawBitmapInt(*tab_inactive_image->image_r, - width() - tab_inactive_image->r_width, 0); -} - -void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) { - int offset = GetX(views::View::APPLY_MIRRORING_TRANSFORMATION) + - background_offset_.x(); - ThemeProvider* tp = GetThemeProvider(); - if (!tp) - NOTREACHED() << "Unable to get theme provider"; - - SkBitmap* tab_bg = GetThemeProvider()->GetBitmapNamed(IDR_THEME_TOOLBAR); - - TabImage* tab_image = &tab_active; - TabImage* alpha = &tab_alpha; - - // Draw left edge. - SkBitmap tab_l = SkBitmapOperations::CreateTiledBitmap( - *tab_bg, offset, 0, tab_image->l_width, height()); - SkBitmap theme_l = - SkBitmapOperations::CreateMaskedBitmap(tab_l, *alpha->image_l); - canvas->DrawBitmapInt(theme_l, 0, 0); - - // Draw right edge. - SkBitmap tab_r = SkBitmapOperations::CreateTiledBitmap(*tab_bg, - offset + width() - tab_image->r_width, 0, tab_image->r_width, height()); - SkBitmap theme_r = - SkBitmapOperations::CreateMaskedBitmap(tab_r, *alpha->image_r); - canvas->DrawBitmapInt(theme_r, width() - tab_image->r_width, 0); - - // Draw center. Instead of masking out the top portion we simply skip over it - // by incrementing by kDropShadowHeight, since it's a simple rectangle. - canvas->TileImageInt(*tab_bg, - offset + tab_image->l_width, - kDropShadowHeight + tab_image->y_offset, - tab_image->l_width, - kDropShadowHeight + tab_image->y_offset, - width() - tab_image->l_width - tab_image->r_width, - height() - kDropShadowHeight - tab_image->y_offset); - - // Now draw the highlights/shadows around the tab edge. - canvas->DrawBitmapInt(*tab_image->image_l, 0, 0); - canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, - width() - tab_image->l_width - tab_image->r_width, height()); - canvas->DrawBitmapInt(*tab_image->image_r, width() - tab_image->r_width, 0); -} - -int Tab::IconCapacity() const { - if (height() < GetMinimumUnselectedSize().height()) - return 0; - return (width() - kLeftPadding - kRightPadding) / kFavIconSize; -} - -bool Tab::ShouldShowIcon() const { - if (data().mini && height() >= GetMinimumUnselectedSize().height()) - return true; - if (!data().show_icon) { - return false; - } else if (IsSelected()) { - // The selected tab clips favicon before close button. - return IconCapacity() >= 2; - } - // Non-selected tabs clip close button before favicon. - return IconCapacity() >= 1; -} - -bool Tab::ShouldShowCloseBox() const { - // The selected tab never clips close button. - return !data().mini && IsCloseable() && - (IsSelected() || IconCapacity() >= 3); -} - -double Tab::GetThrobValue() { - if (pulse_animation() && pulse_animation()->is_animating()) - return pulse_animation()->GetCurrentValue() * kHoverOpacity; - - return hover_animation() ? - kHoverOpacity * hover_animation()->GetCurrentValue() : 0; -} - -//////////////////////////////////////////////////////////////////////////////// -// Tab, private: - -// static -void Tab::LoadTabImages() { - // We're not letting people override tab images just yet. - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - - tab_alpha.image_l = rb.GetBitmapNamed(IDR_TAB_ALPHA_LEFT); - tab_alpha.image_r = rb.GetBitmapNamed(IDR_TAB_ALPHA_RIGHT); - - tab_active.image_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT); - tab_active.image_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER); - tab_active.image_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT); - tab_active.l_width = tab_active.image_l->width(); - tab_active.r_width = tab_active.image_r->width(); - - tab_inactive.image_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT); - tab_inactive.image_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER); - tab_inactive.image_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT); - tab_inactive.l_width = tab_inactive.image_l->width(); - tab_inactive.r_width = tab_inactive.image_r->width(); -} diff --git a/chrome/browser/views/tabs/tab.h b/chrome/browser/views/tabs/tab.h index e99a8fd..11076c1 100644 --- a/chrome/browser/views/tabs/tab.h +++ b/chrome/browser/views/tabs/tab.h @@ -6,136 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_TAB_H_ #pragma once -#include <string> - -#include "base/scoped_ptr.h" -#include "chrome/browser/views/tabs/base_tab.h" -#include "gfx/point.h" - -class MultiAnimation; -class SlideAnimation; - -/////////////////////////////////////////////////////////////////////////////// -// -// TabRenderer -// -// A View that renders a Tab, either in a TabStrip or in a DraggedTabView. -// -/////////////////////////////////////////////////////////////////////////////// -class Tab : public BaseTab { - public: - // The menu button's class name. - static const char kViewClassName[]; - - explicit Tab(TabController* controller); - virtual ~Tab(); - - // Start/stop the mini-tab title animation. - void StartMiniTabTitleAnimation(); - void StopMiniTabTitleAnimation(); - - // Set the background offset used to match the image in the inactive tab - // to the frame image. - void SetBackgroundOffset(const gfx::Point& offset) { - background_offset_ = offset; - } - - // Paints the icon. Most of the time you'll want to invoke Paint directly, but - // in certain situations this invoked outside of Paint. - void PaintIcon(gfx::Canvas* canvas); - - // Returns the minimum possible size of a single unselected Tab. - static gfx::Size GetMinimumUnselectedSize(); - // Returns the minimum possible size of a selected Tab. Selected tabs must - // always show a close button and have a larger minimum size than unselected - // tabs. - static gfx::Size GetMinimumSelectedSize(); - // Returns the preferred size of a single Tab, assuming space is - // available. - static gfx::Size GetStandardSize(); - - // Returns the width for mini-tabs. Mini-tabs always have this width. - static int GetMiniWidth(); - - // Loads the images to be used for the tab background. - static void LoadTabImages(); - - protected: - virtual const gfx::Rect& title_bounds() const { return title_bounds_; } - - // BaseTab overrides: - virtual void DataChanged(const TabRendererData& old); - - private: - // Overridden from views::View: - virtual void Paint(gfx::Canvas* canvas); - virtual void Layout(); - virtual void OnThemeChanged(); - virtual std::string GetClassName() const { return kViewClassName; } - virtual bool HasHitTestMask() const; - virtual void GetHitTestMask(gfx::Path* path) const; - virtual bool GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin); - - // Paint various portions of the Tab - void PaintTabBackground(gfx::Canvas* canvas); - void PaintInactiveTabBackgroundWithTitleChange(gfx::Canvas* canvas); - void PaintInactiveTabBackground(gfx::Canvas* canvas); - void PaintActiveTabBackground(gfx::Canvas* canvas); - - // Returns the number of favicon-size elements that can fit in the tab's - // current size. - int IconCapacity() const; - - // Returns whether the Tab should display a favicon. - bool ShouldShowIcon() const; - - // Returns whether the Tab should display a close button. - bool ShouldShowCloseBox() const; - - // Gets the throb value for the tab. When a tab is not selected the - // active background is drawn at |GetThrobValue()|%. This is used for hover, - // mini tab title change and pulsing. - double GetThrobValue(); - - // The bounds of various sections of the display. - gfx::Rect favicon_bounds_; - gfx::Rect title_bounds_; - - // The offset used to paint the inactive background image. - gfx::Point background_offset_; - - // Hover animation. - scoped_ptr<SlideAnimation> hover_animation_; - - // Animation used when the title of an inactive mini tab changes. - scoped_ptr<MultiAnimation> mini_title_animation_; - - struct TabImage { - SkBitmap* image_l; - SkBitmap* image_c; - SkBitmap* image_r; - int l_width; - int r_width; - int y_offset; - }; - static TabImage tab_active; - static TabImage tab_inactive; - static TabImage tab_alpha; - - // Whether we're showing the icon. It is cached so that we can detect when it - // changes and layout appropriately. - bool showing_icon_; - - // Whether we are showing the close button. It is cached so that we can - // detect when it changes and layout appropriately. - bool showing_close_button_; - - // The current color of the close button. - SkColor close_button_color_; - - static bool initialized_; - - DISALLOW_COPY_AND_ASSIGN(Tab); -}; +#include "chrome/browser/ui/views/tabs/tab.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_TAB_H_ + diff --git a/chrome/browser/views/tabs/tab_controller.h b/chrome/browser/views/tabs/tab_controller.h index abaaf0f..5205f5e 100644 --- a/chrome/browser/views/tabs/tab_controller.h +++ b/chrome/browser/views/tabs/tab_controller.h @@ -6,54 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_ #pragma once -class BaseTab; - -namespace gfx { -class Point; -} -namespace views { -class MouseEvent; -} - -// Controller for tabs. -class TabController { - public: - // Selects the tab. - virtual void SelectTab(BaseTab* tab) = 0; - - // Closes the tab. - virtual void CloseTab(BaseTab* tab) = 0; - - // Shows a context menu for the tab at the specified point in screen coords. - virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p) = 0; - - // Returns true if the specified Tab is selected. - virtual bool IsTabSelected(const BaseTab* tab) const = 0; - - // Returns true if the specified Tab is pinned. - virtual bool IsTabPinned(const BaseTab* tab) const = 0; - - // Returns true if the specified Tab is closeable. - virtual bool IsTabCloseable(const BaseTab* tab) const = 0; - - // Potentially starts a drag for the specified Tab. - virtual void MaybeStartDrag(BaseTab* tab, const views::MouseEvent& event) = 0; - - // Continues dragging a Tab. - virtual void ContinueDrag(const views::MouseEvent& event) = 0; - - // Ends dragging a Tab. |canceled| is true if the drag was aborted in a way - // other than the user releasing the mouse. Returns whether the tab has been - // destroyed. - virtual bool EndDrag(bool canceled) = 0; - - // Returns the tab that contains the specified coordinates, in terms of |tab|, - // or NULL if there is no tab that contains the specified point. - virtual BaseTab* GetTabAt(BaseTab* tab, - const gfx::Point& tab_in_tab_coordinates) = 0; - - protected: - virtual ~TabController() {} -}; +#include "chrome/browser/ui/views/tabs/tab_controller.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_TAB_CONTROLLER_H_ + diff --git a/chrome/browser/views/tabs/tab_dragging_test.cc b/chrome/browser/views/tabs/tab_dragging_test.cc deleted file mode 100644 index 2cb0171..0000000 --- a/chrome/browser/views/tabs/tab_dragging_test.cc +++ /dev/null @@ -1,515 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/command_line.h" -#include "base/file_util.h" -#include "chrome/app/chrome_command_ids.h" -#include "chrome/browser/view_ids.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/automation/tab_proxy.h" -#include "chrome/test/automation/browser_proxy.h" -#include "chrome/test/automation/window_proxy.h" -#include "chrome/test/ui/ui_test.h" -#include "gfx/rect.h" -#include "googleurl/src/gurl.h" -#include "net/base/net_util.h" -#include "views/event.h" - -#if defined(OS_LINUX) -// This test doesn't make sense on chromeos as chromeos doesn't allow dragging -// tabs out. -#define MAYBE_Tab2OutOfTabStrip DISABLED_Tab2OutOfTabStrip -#else -// Flaky, http://crbug.com/62311. -#define MAYBE_Tab2OutOfTabStrip FLAKY_Tab2OutOfTabStrip -#endif - -#if defined(OS_LINUX) -// Disabled on Toolkit views bot. See http://crbug.com/42614 -#define MAYBE_Tab1Tab3Escape DISABLED_Tab1Tab3Escape -#elif defined(OS_WIN) -// Disabled on Windows. See http://crbug.com/57687 -#define MAYBE_Tab1Tab3Escape DISABLED_Tab1Tab3Escape -#else -#define MAYBE_Tab1Tab3Escape Tab1Tab3Escape -#endif - -// These tests fail on Linux because we haven't implemented all of tab dragging -// (it's not needed on chromeos). See http://crbug.com/10941 -#if defined(OS_LINUX) -#define MAYBE_Tab1Tab2 DISABLED_Tab1Tab2 -#define MAYBE_Tab1Tab3 DISABLED_Tab1Tab3 -#else -// Flaky, http://crbug.com/62311. -#define MAYBE_Tab1Tab2 FLAKY_Tab1Tab2 -#define MAYBE_Tab1Tab3 FLAKY_Tab1Tab3 -#endif - -class TabDraggingTest : public UITest { - protected: - TabDraggingTest() { - show_window_ = true; - } -}; - -// Automated UI test to open three tabs in a new window, and drag Tab_1 into -// the position of Tab_2. -TEST_F(TabDraggingTest, MAYBE_Tab1Tab2) { - scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - ASSERT_TRUE(browser.get()); - scoped_refptr<WindowProxy> window(browser->GetWindow()); - ASSERT_TRUE(window.get()); - - // Get initial tab count. - int initial_tab_count = 0; - ASSERT_TRUE(browser->GetTabCount(&initial_tab_count)); - ASSERT_TRUE(1 == initial_tab_count); - - // Get Tab_1 which comes with the browser window. - scoped_refptr<TabProxy> tab1(browser->GetTab(0)); - ASSERT_TRUE(tab1.get()); - GURL tab1_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url)); - - // Add Tab_2. - GURL tab2_url("about:"); - ASSERT_TRUE(browser->AppendTab(tab2_url)); - scoped_refptr<TabProxy> tab2(browser->GetTab(1)); - ASSERT_TRUE(tab2.get()); - - // Add Tab_3. - GURL tab3_url("about:plugins"); - ASSERT_TRUE(browser->AppendTab(tab3_url)); - scoped_refptr<TabProxy> tab3(browser->GetTab(2)); - ASSERT_TRUE(tab3.get()); - - // Make sure 3 tabs are open. - ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2)); - - // Get bounds for the tabs. - gfx::Rect bounds1; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false)); - EXPECT_LT(0, bounds1.x()); - EXPECT_LT(0, bounds1.width()); - EXPECT_LT(0, bounds1.height()); - - gfx::Rect bounds2; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false)); - EXPECT_LT(0, bounds2.width()); - EXPECT_LT(0, bounds2.height()); - EXPECT_LT(bounds1.x(), bounds2.x()); - EXPECT_EQ(bounds2.y(), bounds1.y()); - - gfx::Rect bounds3; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false)); - EXPECT_LT(0, bounds3.width()); - EXPECT_LT(0, bounds3.height()); - EXPECT_LT(bounds2.x(), bounds3.x()); - EXPECT_EQ(bounds3.y(), bounds2.y()); - - // Get url Bar bounds. - gfx::Rect urlbar_bounds; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds, - false)); - EXPECT_LT(0, urlbar_bounds.x()); - EXPECT_LT(0, urlbar_bounds.y()); - EXPECT_LT(0, urlbar_bounds.width()); - EXPECT_LT(0, urlbar_bounds.height()); - - /* - TEST: Move Tab_1 to the position of Tab_2 - ____________ ____________ ____________ - / \ / \ / \ - | Tab_1 | Tab_2 | Tab_3 | - ---- ---- ---- ---- ---- ---- ---- ---- ---- - x---- ----> - ____________ - / X \ - | Tab_1 | - ---- ---- ---- - */ - - gfx::Point start(bounds1.x() + bounds1.width() / 2, - bounds1.y() + bounds1.height() / 2); - gfx::Point end(start.x() + 2 * bounds1.width() / 3, start.y()); - ASSERT_TRUE(browser->SimulateDrag(start, end, - views::Event::EF_LEFT_BUTTON_DOWN, - false)); - - // Now check for expected results. - tab1 = browser->GetTab(0); - ASSERT_TRUE(tab1.get()); - GURL tab1_new_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url)); - - tab2 = browser->GetTab(1); - ASSERT_TRUE(tab2.get()); - GURL tab2_new_url; - ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url)); - - EXPECT_EQ(tab1_url.spec(), tab2_new_url.spec()); - EXPECT_EQ(tab2_url.spec(), tab1_new_url.spec()); -} - -// Drag Tab_1 into the position of Tab_3. -TEST_F(TabDraggingTest, MAYBE_Tab1Tab3) { - scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - ASSERT_TRUE(browser.get()); - scoped_refptr<WindowProxy> window(browser->GetWindow()); - ASSERT_TRUE(window.get()); - - // Get initial tab count. - int initial_tab_count = 0; - ASSERT_TRUE(browser->GetTabCount(&initial_tab_count)); - ASSERT_TRUE(1 == initial_tab_count); - - // Get Tab_1 which comes with the browser window. - scoped_refptr<TabProxy> tab1(browser->GetTab(0)); - ASSERT_TRUE(tab1.get()); - GURL tab1_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url)); - - // Add Tab_2. - GURL tab2_url("about:"); - ASSERT_TRUE(browser->AppendTab(tab2_url)); - scoped_refptr<TabProxy> tab2(browser->GetTab(1)); - ASSERT_TRUE(tab2.get()); - - // Add Tab_3. - GURL tab3_url("about:plugins"); - ASSERT_TRUE(browser->AppendTab(tab3_url)); - scoped_refptr<TabProxy> tab3(browser->GetTab(2)); - ASSERT_TRUE(tab3.get()); - - // Make sure 3 tabs are open. - ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2)); - - // Get bounds for the tabs. - gfx::Rect bounds1; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false)); - EXPECT_LT(0, bounds1.x()); - EXPECT_LT(0, bounds1.width()); - EXPECT_LT(0, bounds1.height()); - - gfx::Rect bounds2; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false)); - EXPECT_LT(0, bounds2.width()); - EXPECT_LT(0, bounds2.height()); - EXPECT_LT(bounds1.x(), bounds2.x()); - EXPECT_EQ(bounds2.y(), bounds1.y()); - - gfx::Rect bounds3; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false)); - EXPECT_LT(0, bounds3.width()); - EXPECT_LT(0, bounds3.height()); - EXPECT_LT(bounds2.x(), bounds3.x()); - EXPECT_EQ(bounds3.y(), bounds2.y()); - - // Get url Bar bounds. - gfx::Rect urlbar_bounds; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds, - false)); - EXPECT_LT(0, urlbar_bounds.x()); - EXPECT_LT(0, urlbar_bounds.y()); - EXPECT_LT(0, urlbar_bounds.width()); - EXPECT_LT(0, urlbar_bounds.height()); - - /* - TEST: Move Tab_1 to the middle position of Tab_3 - ____________ ____________ ____________ - / \ / \ / \ - | Tab_1 | Tab_2 | Tab_3 | - ---- ---- ---- ---- ---- ---- ---- ---- ---- - x---- ---- ---- ---- ---- ----> - ____________ - / X \ - | Tab_1 | - ---- ---- ---- - */ - - gfx::Point start(bounds1.x() + bounds1.width() / 2, - bounds1.y() + bounds1.height() / 2); - gfx::Point end(start.x() + bounds1.width() / 2 + bounds2.width() + - bounds3.width() / 2, - start.y()); - ASSERT_TRUE(browser->SimulateDrag(start, end, - views::Event::EF_LEFT_BUTTON_DOWN, - false)); - - // Now check for expected results. - tab1 = browser->GetTab(0); - ASSERT_TRUE(tab1.get()); - GURL tab1_new_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url)); - - tab2 = browser->GetTab(1); - ASSERT_TRUE(tab2.get()); - GURL tab2_new_url; - ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url)); - - tab3 = browser->GetTab(2); - ASSERT_TRUE(tab3.get()); - GURL tab3_new_url; - ASSERT_TRUE(tab3->GetCurrentURL(&tab3_new_url)); - - EXPECT_EQ(tab1_new_url.spec(), tab2_url.spec()); - EXPECT_EQ(tab2_new_url.spec(), tab3_url.spec()); - EXPECT_EQ(tab3_new_url.spec(), tab1_url.spec()); -} - -// Drag Tab_1 into the position of Tab_3, and press ESCAPE before releasing the -// left mouse button. -TEST_F(TabDraggingTest, MAYBE_Tab1Tab3Escape) { - scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - ASSERT_TRUE(browser.get()); - scoped_refptr<WindowProxy> window(browser->GetWindow()); - ASSERT_TRUE(window.get()); - - // Get initial tab count. - int initial_tab_count = 0; - ASSERT_TRUE(browser->GetTabCount(&initial_tab_count)); - ASSERT_TRUE(1 == initial_tab_count); - - // Get Tab_1 which comes with the browser window. - scoped_refptr<TabProxy> tab1(browser->GetTab(0)); - ASSERT_TRUE(tab1.get()); - GURL tab1_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url)); - - // Add Tab_2. - GURL tab2_url("about:blank"); - ASSERT_TRUE(browser->AppendTab(tab2_url)); - scoped_refptr<TabProxy> tab2(browser->GetTab(1)); - ASSERT_TRUE(tab2.get()); - - // Add Tab_3. - GURL tab3_url("about:plugins"); - ASSERT_TRUE(browser->AppendTab(tab3_url)); - scoped_refptr<TabProxy> tab3(browser->GetTab(2)); - ASSERT_TRUE(tab3.get()); - - // Make sure 3 tabs are open. - ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2)); - - // Get bounds for the tabs. - gfx::Rect bounds1; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false)); - EXPECT_LT(0, bounds1.x()); - EXPECT_LT(0, bounds1.width()); - EXPECT_LT(0, bounds1.height()); - - gfx::Rect bounds2; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false)); - EXPECT_LT(0, bounds2.width()); - EXPECT_LT(0, bounds2.height()); - EXPECT_LT(bounds1.x(), bounds2.x()); - EXPECT_EQ(bounds2.y(), bounds1.y()); - - gfx::Rect bounds3; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false)); - EXPECT_LT(0, bounds3.width()); - EXPECT_LT(0, bounds3.height()); - EXPECT_LT(bounds2.x(), bounds3.x()); - EXPECT_EQ(bounds3.y(), bounds2.y()); - - // Get url Bar bounds. - gfx::Rect urlbar_bounds; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds, - false)); - EXPECT_LT(0, urlbar_bounds.x()); - EXPECT_LT(0, urlbar_bounds.y()); - EXPECT_LT(0, urlbar_bounds.width()); - EXPECT_LT(0, urlbar_bounds.height()); - - /* - TEST: Move Tab_1 to the middle position of Tab_3 - ____________ ____________ ____________ - / \ / \ / \ - | Tab_1 | Tab_2 | Tab_3 | - ---- ---- ---- ---- ---- ---- ---- ---- ---- - x---- ---- ---- ---- ---- ----> + ESCAPE - ____________ - / X \ - | Tab_1 | - ---- ---- ---- - */ - - gfx::Point start(bounds1.x() + bounds1.width() / 2, - bounds1.y() + bounds1.height() / 2); - gfx::Point end(start.x() + bounds1.width() / 2 + bounds2.width() + - bounds3.width() / 2, - start.y()); - - // Simulate drag with 'true' as the last parameter. This will interrupt - // in-flight with Escape. - ASSERT_TRUE(browser->SimulateDrag(start, end, - views::Event::EF_LEFT_BUTTON_DOWN, - true)); - - // Now check for expected results. - tab1 = browser->GetTab(0); - ASSERT_TRUE(tab1.get()); - GURL tab1_new_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url)); - - tab2 = browser->GetTab(1); - ASSERT_TRUE(tab2.get()); - GURL tab2_new_url; - ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url)); - - tab3 = browser->GetTab(2); - ASSERT_TRUE(tab3.get()); - GURL tab3_new_url; - ASSERT_TRUE(tab3->GetCurrentURL(&tab3_new_url)); - - // The tabs should be in their original positions. - EXPECT_EQ(tab1_new_url.spec(), tab1_url.spec()); - EXPECT_EQ(tab2_new_url.spec(), tab2_url.spec()); - EXPECT_EQ(tab3_new_url.spec(), tab3_url.spec()); -} - -// Drag Tab_2 out of the Tab strip. A new window should open with this tab. -TEST_F(TabDraggingTest, MAYBE_Tab2OutOfTabStrip) { - scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); - ASSERT_TRUE(browser.get()); - scoped_refptr<WindowProxy> window(browser->GetWindow()); - ASSERT_TRUE(window.get()); - - // Get initial tab count. - int initial_tab_count = 0; - ASSERT_TRUE(browser->GetTabCount(&initial_tab_count)); - ASSERT_TRUE(1 == initial_tab_count); - - // Get Tab_1 which comes with the browser window. - scoped_refptr<TabProxy> tab1(browser->GetTab(0)); - ASSERT_TRUE(tab1.get()); - GURL tab1_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_url)); - - // Add Tab_2. - GURL tab2_url("about:version"); - ASSERT_TRUE(browser->AppendTab(tab2_url)); - scoped_refptr<TabProxy> tab2(browser->GetTab(1)); - ASSERT_TRUE(tab2.get()); - - // Add Tab_3. - GURL tab3_url("about:plugins"); - ASSERT_TRUE(browser->AppendTab(tab3_url)); - scoped_refptr<TabProxy> tab3(browser->GetTab(2)); - ASSERT_TRUE(tab3.get()); - - // Make sure 3 tabs are opened. - ASSERT_TRUE(browser->WaitForTabCountToBecome(initial_tab_count + 2)); - - // Make sure all the tab URL specs are different. - ASSERT_TRUE(tab1_url != tab2_url); - ASSERT_TRUE(tab1_url != tab3_url); - ASSERT_TRUE(tab2_url != tab3_url); - - // Get bounds for the tabs. - gfx::Rect bounds1; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_0, &bounds1, false)); - EXPECT_LT(0, bounds1.x()); - EXPECT_LT(0, bounds1.width()); - EXPECT_LT(0, bounds1.height()); - - gfx::Rect bounds2; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_1, &bounds2, false)); - EXPECT_LT(0, bounds2.width()); - EXPECT_LT(0, bounds2.height()); - EXPECT_LT(bounds1.x(), bounds2.x()); - EXPECT_EQ(bounds2.y(), bounds1.y()); - - gfx::Rect bounds3; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_TAB_2, &bounds3, false)); - EXPECT_LT(0, bounds3.width()); - EXPECT_LT(0, bounds3.height()); - EXPECT_LT(bounds2.x(), bounds3.x()); - EXPECT_EQ(bounds3.y(), bounds2.y()); - - // Get url Bar bounds. - gfx::Rect urlbar_bounds; - ASSERT_TRUE(window->GetViewBounds(VIEW_ID_LOCATION_BAR, &urlbar_bounds, - false)); - EXPECT_LT(0, urlbar_bounds.x()); - EXPECT_LT(0, urlbar_bounds.y()); - EXPECT_LT(0, urlbar_bounds.width()); - EXPECT_LT(0, urlbar_bounds.height()); - - /* - TEST: Move Tab_2 down, out of the tab strip. - This should result in the following: - 1- Tab_3 shift left in place of Tab_2 in Window 1 - 2- Tab_1 to remain in its place - 3- Tab_2 openes in a new window - - ____________ ____________ ____________ - / \ / \ / \ - | Tab_1 | Tab_2 | Tab_3 | - ---- ---- ---- ---- ---- ---- ---- ---- ---- - x - | - | (Drag this below, out of tab strip) - V - ____________ - / X \ - | Tab_2 | (New Window) - ---- ---- ---- ---- ---- ---- ---- - */ - - gfx::Point start(bounds2.x() + bounds2.width() / 2, - bounds2.y() + bounds2.height() / 2); - gfx::Point end(start.x(), - start.y() + 3 * urlbar_bounds.height()); - - // Simulate tab drag. - ASSERT_TRUE(browser->SimulateDrag(start, end, - views::Event::EF_LEFT_BUTTON_DOWN, - false)); - - // Now, first make sure that the old window has only two tabs remaining. - int new_tab_count = 0; - ASSERT_TRUE(browser->GetTabCount(&new_tab_count)); - ASSERT_EQ(2, new_tab_count); - - // Get the two tabs - they are called Tab_1 and Tab_2 in the old window. - tab1 = browser->GetTab(0); - ASSERT_TRUE(tab1.get()); - GURL tab1_new_url; - ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url)); - - tab2 = browser->GetTab(1); - ASSERT_TRUE(tab2.get()); - GURL tab2_new_url; - ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url)); - - // Now check for proper shifting of tabs; i.e., Tab_3 in window 1 should - // shift left to the position of Tab_2; Tab_1 should stay where it was. - EXPECT_EQ(tab1_new_url.spec(), tab1_url.spec()); - EXPECT_EQ(tab2_new_url.spec(), tab3_url.spec()); - - // Now check to make sure a new window has opened. - scoped_refptr<BrowserProxy> browser2(automation()->GetBrowserWindow(1)); - ASSERT_TRUE(browser2.get()); - scoped_refptr<WindowProxy> window2(browser2->GetWindow()); - ASSERT_TRUE(window2.get()); - - // Make sure that the new window has only one tab. - int tab_count_window_2 = 0; - ASSERT_TRUE(browser2->GetTabCount(&tab_count_window_2)); - ASSERT_EQ(1, tab_count_window_2); - - // Get Tab_1_2 which should be Tab_1 in Window 2. - scoped_refptr<TabProxy> tab1_2(browser2->GetTab(0)); - ASSERT_TRUE(tab1_2.get()); - GURL tab1_2_url; - ASSERT_TRUE(tab1_2->GetCurrentURL(&tab1_2_url)); - - // Tab_1_2 of Window 2 should essentially be Tab_2 of Window 1. - EXPECT_EQ(tab1_2_url.spec(), tab2_url.spec()); - EXPECT_NE(tab1_2_url.spec(), tab1_url.spec()); - EXPECT_NE(tab1_2_url.spec(), tab3_url.spec()); -} diff --git a/chrome/browser/views/tabs/tab_renderer_data.h b/chrome/browser/views/tabs/tab_renderer_data.h index 31e84ed..dca47c9 100644 --- a/chrome/browser/views/tabs/tab_renderer_data.h +++ b/chrome/browser/views/tabs/tab_renderer_data.h @@ -6,41 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_DATA_H_ #pragma once -#include "base/string16.h" -#include "third_party/skia/include/core/SkBitmap.h" - -// Wraps the state needed by the renderers. -struct TabRendererData { - // Different types of network activity for a tab. The NetworkState of a tab - // may be used to alter the UI (e.g. show different kinds of loading - // animations). - enum NetworkState { - NETWORK_STATE_NONE, // no network activity. - NETWORK_STATE_WAITING, // waiting for a connection. - NETWORK_STATE_LOADING, // connected, transferring data. - }; - - TabRendererData() - : network_state(NETWORK_STATE_NONE), - loading(false), - crashed(false), - off_the_record(false), - show_icon(true), - mini(false), - blocked(false), - app(false) { - } - - SkBitmap favicon; - NetworkState network_state; - string16 title; - bool loading; - bool crashed; - bool off_the_record; - bool show_icon; - bool mini; - bool blocked; - bool app; -}; +#include "chrome/browser/ui/views/tabs/tab_renderer_data.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_TAB_RENDERER_DATA_H_ + diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc deleted file mode 100644 index 9b25dfa..0000000 --- a/chrome/browser/views/tabs/tab_strip.cc +++ /dev/null @@ -1,982 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/views/tabs/tab_strip.h" - -#include "app/animation_container.h" -#include "app/drag_drop_types.h" -#include "app/l10n_util.h" -#include "app/resource_bundle.h" -#include "base/compiler_specific.h" -#include "base/stl_util-inl.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/defaults.h" -#include "chrome/browser/themes/browser_theme_provider.h" -#include "chrome/browser/view_ids.h" -#include "chrome/browser/views/tabs/tab.h" -#include "chrome/browser/views/tabs/tab_strip_controller.h" -#include "chrome/common/pref_names.h" -#include "gfx/canvas_skia.h" -#include "gfx/path.h" -#include "gfx/size.h" -#include "grit/generated_resources.h" -#include "grit/theme_resources.h" -#include "views/controls/image_view.h" -#include "views/widget/default_theme_provider.h" -#include "views/window/non_client_view.h" -#include "views/window/window.h" - -#if defined(OS_WIN) -#include "app/win_util.h" -#include "views/widget/widget_win.h" -#elif defined(OS_LINUX) -#include "views/widget/widget_gtk.h" -#endif - -#undef min -#undef max - -#if defined(COMPILER_GCC) -// Squash false positive signed overflow warning in GenerateStartAndEndWidths -// when doing 'start_tab_count < end_tab_count'. -#pragma GCC diagnostic ignored "-Wstrict-overflow" -#endif - -using views::DropTargetEvent; - -static const int kNewTabButtonHOffset = -5; -static const int kNewTabButtonVOffset = 5; -static const int kSuspendAnimationsTimeMs = 200; -static const int kTabHOffset = -16; -static const int kTabStripAnimationVSlop = 40; - -// Size of the drop indicator. -static int drop_indicator_width; -static int drop_indicator_height; - -static inline int Round(double x) { - // Why oh why is this not in a standard header? - return static_cast<int>(floor(x + 0.5)); -} - -namespace { - -/////////////////////////////////////////////////////////////////////////////// -// NewTabButton -// -// A subclass of button that hit-tests to the shape of the new tab button. - -class NewTabButton : public views::ImageButton { - public: - explicit NewTabButton(views::ButtonListener* listener) - : views::ImageButton(listener) { - } - virtual ~NewTabButton() {} - - protected: - // Overridden from views::View: - virtual bool HasHitTestMask() const { - // When the button is sized to the top of the tab strip we want the user to - // be able to click on complete bounds, and so don't return a custom hit - // mask. - return !browser_defaults::kSizeTabButtonToTopOfTabStrip; - } - virtual void GetHitTestMask(gfx::Path* path) const { - DCHECK(path); - - SkScalar w = SkIntToScalar(width()); - - // These values are defined by the shape of the new tab bitmap. Should that - // bitmap ever change, these values will need to be updated. They're so - // custom it's not really worth defining constants for. - path->moveTo(0, 1); - path->lineTo(w - 7, 1); - path->lineTo(w - 4, 4); - path->lineTo(w, 16); - path->lineTo(w - 1, 17); - path->lineTo(7, 17); - path->lineTo(4, 13); - path->lineTo(0, 1); - path->close(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(NewTabButton); -}; - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// TabStrip, public: - -// static -const int TabStrip::mini_to_non_mini_gap_ = 3; - -TabStrip::TabStrip(TabStripController* controller) - : BaseTabStrip(controller, BaseTabStrip::HORIZONTAL_TAB_STRIP), - current_unselected_width_(Tab::GetStandardSize().width()), - current_selected_width_(Tab::GetStandardSize().width()), - available_width_for_tabs_(-1), - in_tab_close_(false), - animation_container_(new AnimationContainer()) { - Init(); -} - -TabStrip::~TabStrip() { - // The animations may reference the tabs. Shut down the animation before we - // delete the tabs. - StopAnimating(false); - - DestroyDragController(); - - // Make sure we unhook ourselves as a message loop observer so that we don't - // crash in the case where the user closes the window after closing a tab - // but before moving the mouse. - RemoveMessageLoopObserver(); - - // The children (tabs) may callback to us from their destructor. Delete them - // so that if they call back we aren't in a weird state. - RemoveAllChildViews(true); -} - -void TabStrip::InitTabStripButtons() { - newtab_button_ = new NewTabButton(this); - if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { - newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, - views::ImageButton::ALIGN_BOTTOM); - } - LoadNewTabButtonImage(); - newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB)); - AddChildView(newtab_button_); -} - -gfx::Rect TabStrip::GetNewTabButtonBounds() { - return newtab_button_->bounds(); -} - -void TabStrip::MouseMovedOutOfView() { - ResizeLayoutTabs(); -} - -//////////////////////////////////////////////////////////////////////////////// -// TabStrip, BaseTabStrip implementation: - -int TabStrip::GetPreferredHeight() { - return GetPreferredSize().height(); -} - -void TabStrip::SetBackgroundOffset(const gfx::Point& offset) { - for (int i = 0; i < tab_count(); ++i) - GetTabAtTabDataIndex(i)->SetBackgroundOffset(offset); -} - -bool TabStrip::IsPositionInWindowCaption(const gfx::Point& point) { - views::View* v = GetViewForPoint(point); - - // If there is no control at this location, claim the hit was in the title - // bar to get a move action. - if (v == this) - return true; - - // Check to see if the point is within the non-button parts of the new tab - // button. The button has a non-rectangular shape, so if it's not in the - // visual portions of the button we treat it as a click to the caption. - gfx::Point point_in_newtab_coords(point); - View::ConvertPointToView(this, newtab_button_, &point_in_newtab_coords); - if (newtab_button_->bounds().Contains(point) && - !newtab_button_->HitTest(point_in_newtab_coords)) { - return true; - } - - // All other regions, including the new Tab button, should be considered part - // of the containing Window's client area so that regular events can be - // processed for them. - return false; -} - -void TabStrip::SetDraggedTabBounds(int tab_index, const gfx::Rect& tab_bounds) { -} - -TabStrip* TabStrip::AsTabStrip() { - return this; -} - -void TabStrip::PrepareForCloseAt(int model_index) { - if (!in_tab_close_ && IsAnimating()) { - // Cancel any current animations. We do this as remove uses the current - // ideal bounds and we need to know ideal bounds is in a good state. - StopAnimating(true); - } - - int model_count = GetModelCount(); - if (model_index + 1 != model_count && model_count > 1) { - // The user is about to close a tab other than the last tab. Set - // available_width_for_tabs_ so that if we do a layout we don't position a - // tab past the end of the second to last tab. We do this so that as the - // user closes tabs with the mouse a tab continues to fall under the mouse. - available_width_for_tabs_ = GetAvailableWidthForTabs( - GetTabAtModelIndex(model_count - 2)); - } - - in_tab_close_ = true; - AddMessageLoopObserver(); -} - -void TabStrip::RemoveTabAt(int model_index) { - if (in_tab_close_ && model_index != GetModelCount()) - StartMouseInitiatedRemoveTabAnimation(model_index); - else - StartRemoveTabAnimation(model_index); -} - -void TabStrip::SelectTabAt(int old_model_index, int new_model_index) { - // We have "tiny tabs" if the tabs are so tiny that the unselected ones are - // a different size to the selected ones. - bool tiny_tabs = current_unselected_width_ != current_selected_width_; - if (!IsAnimating() && (!in_tab_close_ || tiny_tabs)) { - DoLayout(); - } else { - SchedulePaint(); - } - - if (old_model_index >= 0) { - GetTabAtTabDataIndex(ModelIndexToTabIndex(old_model_index))-> - StopMiniTabTitleAnimation(); - } -} - -void TabStrip::TabTitleChangedNotLoading(int model_index) { - Tab* tab = GetTabAtModelIndex(model_index); - if (tab->data().mini && !tab->IsSelected()) - tab->StartMiniTabTitleAnimation(); -} - -void TabStrip::StartHighlight(int model_index) { - GetTabAtModelIndex(model_index)->StartPulse(); -} - -void TabStrip::StopAllHighlighting() { - for (int i = 0; i < tab_count(); ++i) - GetTabAtTabDataIndex(i)->StopPulse(); -} - -BaseTab* TabStrip::CreateTabForDragging() { - Tab* tab = new Tab(NULL); - // Make sure the dragged tab shares our theme provider. We need to explicitly - // do this as during dragging there isn't a theme provider. - tab->set_theme_provider(GetThemeProvider()); - return tab; -} - -/////////////////////////////////////////////////////////////////////////////// -// TabStrip, views::View overrides: - -void TabStrip::PaintChildren(gfx::Canvas* canvas) { - // Tabs are painted in reverse order, so they stack to the left. - Tab* selected_tab = NULL; - Tab* dragging_tab = NULL; - - for (int i = tab_count() - 1; i >= 0; --i) { - Tab* tab = GetTabAtTabDataIndex(i); - // We must ask the _Tab's_ model, not ourselves, because in some situations - // the model will be different to this object, e.g. when a Tab is being - // removed after its TabContents has been destroyed. - if (tab->dragging()) { - dragging_tab = tab; - } else if (!tab->IsSelected()) { - tab->ProcessPaint(canvas); - } else { - selected_tab = tab; - } - } - - if (GetWindow()->GetNonClientView()->UseNativeFrame()) { - // Make sure unselected tabs are somewhat transparent. - SkPaint paint; - paint.setColor(SkColorSetARGB(200, 255, 255, 255)); - paint.setXfermodeMode(SkXfermode::kDstIn_Mode); - paint.setStyle(SkPaint::kFill_Style); - canvas->DrawRectInt(0, 0, width(), - height() - 2, // Visible region that overlaps the toolbar. - paint); - } - - // Paint the selected tab last, so it overlaps all the others. - if (selected_tab) - selected_tab->ProcessPaint(canvas); - - // Paint the New Tab button. - newtab_button_->ProcessPaint(canvas); - - // And the dragged tab. - if (dragging_tab) - dragging_tab->ProcessPaint(canvas); -} - -// Overridden to support automation. See automation_proxy_uitest.cc. -views::View* TabStrip::GetViewByID(int view_id) const { - if (tab_count() > 0) { - if (view_id == VIEW_ID_TAB_LAST) { - return GetTabAtTabDataIndex(tab_count() - 1); - } else if ((view_id >= VIEW_ID_TAB_0) && (view_id < VIEW_ID_TAB_LAST)) { - int index = view_id - VIEW_ID_TAB_0; - if (index >= 0 && index < tab_count()) { - return GetTabAtTabDataIndex(index); - } else { - return NULL; - } - } - } - - return View::GetViewByID(view_id); -} - -gfx::Size TabStrip::GetPreferredSize() { - return gfx::Size(0, Tab::GetMinimumUnselectedSize().height()); -} - -void TabStrip::OnDragEntered(const DropTargetEvent& event) { - // Force animations to stop, otherwise it makes the index calculation tricky. - StopAnimating(true); - - UpdateDropIndex(event); -} - -int TabStrip::OnDragUpdated(const DropTargetEvent& event) { - UpdateDropIndex(event); - return GetDropEffect(event); -} - -void TabStrip::OnDragExited() { - SetDropIndex(-1, false); -} - -int TabStrip::OnPerformDrop(const DropTargetEvent& event) { - if (!drop_info_.get()) - return DragDropTypes::DRAG_NONE; - - const int drop_index = drop_info_->drop_index; - const bool drop_before = drop_info_->drop_before; - - // Hide the drop indicator. - SetDropIndex(-1, false); - - GURL url; - std::wstring title; - if (!event.GetData().GetURLAndTitle(&url, &title) || !url.is_valid()) - return DragDropTypes::DRAG_NONE; - - controller()->PerformDrop(drop_before, drop_index, url); - - return GetDropEffect(event); -} - -AccessibilityTypes::Role TabStrip::GetAccessibleRole() { - return AccessibilityTypes::ROLE_PAGETABLIST; -} - -views::View* TabStrip::GetViewForPoint(const gfx::Point& point) { - // Return any view that isn't a Tab or this TabStrip immediately. We don't - // want to interfere. - views::View* v = View::GetViewForPoint(point); - if (v && v != this && v->GetClassName() != Tab::kViewClassName) - return v; - - // The display order doesn't necessarily match the child list order, so we - // walk the display list hit-testing Tabs. Since the selected tab always - // renders on top of adjacent tabs, it needs to be hit-tested before any - // left-adjacent Tab, so we look ahead for it as we walk. - for (int i = 0; i < tab_count(); ++i) { - Tab* next_tab = i < (tab_count() - 1) ? GetTabAtTabDataIndex(i + 1) : NULL; - if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point)) - return next_tab; - Tab* tab = GetTabAtTabDataIndex(i); - if (IsPointInTab(tab, point)) - return tab; - } - - // No need to do any floating view stuff, we don't use them in the TabStrip. - return this; -} - -void TabStrip::OnThemeChanged() { - LoadNewTabButtonImage(); -} - -BaseTab* TabStrip::CreateTab() { - Tab* tab = new Tab(this); - tab->set_animation_container(animation_container_.get()); - return tab; -} - -void TabStrip::StartInsertTabAnimation(int model_index, bool foreground) { - PrepareForAnimation(); - - // The TabStrip can now use its entire width to lay out Tabs. - in_tab_close_ = false; - available_width_for_tabs_ = -1; - - GenerateIdealBounds(); - - int tab_data_index = ModelIndexToTabIndex(model_index); - BaseTab* tab = base_tab_at_tab_index(tab_data_index); - if (model_index == 0) { - tab->SetBounds(0, ideal_bounds(tab_data_index).y(), 0, - ideal_bounds(tab_data_index).height()); - } else { - BaseTab* last_tab = base_tab_at_tab_index(tab_data_index - 1); - tab->SetBounds(last_tab->bounds().right() + kTabHOffset, - ideal_bounds(tab_data_index).y(), 0, - ideal_bounds(tab_data_index).height()); - } - - AnimateToIdealBounds(); -} - -void TabStrip::StartMoveTabAnimation() { - PrepareForAnimation(); - - GenerateIdealBounds(); - AnimateToIdealBounds(); -} - -void TabStrip::AnimateToIdealBounds() { - for (int i = 0; i < tab_count(); ++i) { - Tab* tab = GetTabAtTabDataIndex(i); - if (!tab->closing() && !tab->dragging()) - bounds_animator().AnimateViewTo(tab, ideal_bounds(i)); - } - - bounds_animator().AnimateViewTo(newtab_button_, newtab_button_bounds_); -} - -bool TabStrip::ShouldHighlightCloseButtonAfterRemove() { - return in_tab_close_; -} - -void TabStrip::DoLayout() { - BaseTabStrip::DoLayout(); - - newtab_button_->SetBounds(newtab_button_bounds_); -} - -void TabStrip::ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child) { - if (is_add && child == this) - InitTabStripButtons(); -} - -/////////////////////////////////////////////////////////////////////////////// -// TabStrip, Tab::Delegate implementation: - -bool TabStrip::IsTabSelected(const BaseTab* btr) const { - const Tab* tab = static_cast<const Tab*>(btr); - return !tab->closing() && BaseTabStrip::IsTabSelected(btr); -} - -/////////////////////////////////////////////////////////////////////////////// -// TabStrip, views::BaseButton::ButtonListener implementation: - -void TabStrip::ButtonPressed(views::Button* sender, const views::Event& event) { - if (sender == newtab_button_) - controller()->CreateNewTab(); -} - -/////////////////////////////////////////////////////////////////////////////// -// TabStrip, private: - -void TabStrip::Init() { - SetID(VIEW_ID_TAB_STRIP); - newtab_button_bounds_.SetRect(0, 0, kNewTabButtonWidth, kNewTabButtonHeight); - if (browser_defaults::kSizeTabButtonToTopOfTabStrip) { - newtab_button_bounds_.set_height( - kNewTabButtonHeight + kNewTabButtonVOffset); - } - if (drop_indicator_width == 0) { - // Direction doesn't matter, both images are the same size. - SkBitmap* drop_image = GetDropArrowImage(true); - drop_indicator_width = drop_image->width(); - drop_indicator_height = drop_image->height(); - } -} - -void TabStrip::LoadNewTabButtonImage() { - ThemeProvider* tp = GetThemeProvider(); - - // If we don't have a theme provider yet, it means we do not have a - // root view, and are therefore in a test. - bool in_test = false; - if (tp == NULL) { - tp = new views::DefaultThemeProvider(); - in_test = true; - } - - SkBitmap* bitmap = tp->GetBitmapNamed(IDR_NEWTAB_BUTTON); - SkColor color = tp->GetColor(BrowserThemeProvider::COLOR_BUTTON_BACKGROUND); - SkBitmap* background = tp->GetBitmapNamed( - IDR_THEME_WINDOW_CONTROL_BACKGROUND); - - newtab_button_->SetImage(views::CustomButton::BS_NORMAL, bitmap); - newtab_button_->SetImage(views::CustomButton::BS_PUSHED, - tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_P)); - newtab_button_->SetImage(views::CustomButton::BS_HOT, - tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_H)); - newtab_button_->SetBackground(color, background, - tp->GetBitmapNamed(IDR_NEWTAB_BUTTON_MASK)); - if (in_test) - delete tp; -} - -Tab* TabStrip::GetTabAtTabDataIndex(int tab_data_index) const { - return static_cast<Tab*>(base_tab_at_tab_index(tab_data_index)); -} - -Tab* TabStrip::GetTabAtModelIndex(int model_index) const { - return GetTabAtTabDataIndex(ModelIndexToTabIndex(model_index)); -} - -void TabStrip::GetCurrentTabWidths(double* unselected_width, - double* selected_width) const { - *unselected_width = current_unselected_width_; - *selected_width = current_selected_width_; -} - -void TabStrip::GetDesiredTabWidths(int tab_count, - int mini_tab_count, - double* unselected_width, - double* selected_width) const { - DCHECK(tab_count >= 0 && mini_tab_count >= 0 && mini_tab_count <= tab_count); - const double min_unselected_width = Tab::GetMinimumUnselectedSize().width(); - const double min_selected_width = Tab::GetMinimumSelectedSize().width(); - - *unselected_width = min_unselected_width; - *selected_width = min_selected_width; - - if (tab_count == 0) { - // Return immediately to avoid divide-by-zero below. - return; - } - - // Determine how much space we can actually allocate to tabs. - int available_width; - if (available_width_for_tabs_ < 0) { - available_width = width(); - available_width -= (kNewTabButtonHOffset + newtab_button_bounds_.width()); - } else { - // Interesting corner case: if |available_width_for_tabs_| > the result - // of the calculation in the conditional arm above, the strip is in - // overflow. We can either use the specified width or the true available - // width here; the first preserves the consistent "leave the last tab under - // the user's mouse so they can close many tabs" behavior at the cost of - // prolonging the glitchy appearance of the overflow state, while the second - // gets us out of overflow as soon as possible but forces the user to move - // their mouse for a few tabs' worth of closing. We choose visual - // imperfection over behavioral imperfection and select the first option. - available_width = available_width_for_tabs_; - } - - if (mini_tab_count > 0) { - available_width -= mini_tab_count * (Tab::GetMiniWidth() + kTabHOffset); - tab_count -= mini_tab_count; - if (tab_count == 0) { - *selected_width = *unselected_width = Tab::GetStandardSize().width(); - return; - } - // Account for gap between the last mini-tab and first non-mini-tab. - available_width -= mini_to_non_mini_gap_; - } - - // Calculate the desired tab widths by dividing the available space into equal - // portions. Don't let tabs get larger than the "standard width" or smaller - // than the minimum width for each type, respectively. - const int total_offset = kTabHOffset * (tab_count - 1); - const double desired_tab_width = std::min((static_cast<double>( - available_width - total_offset) / static_cast<double>(tab_count)), - static_cast<double>(Tab::GetStandardSize().width())); - *unselected_width = std::max(desired_tab_width, min_unselected_width); - *selected_width = std::max(desired_tab_width, min_selected_width); - - // When there are multiple tabs, we'll have one selected and some unselected - // tabs. If the desired width was between the minimum sizes of these types, - // try to shrink the tabs with the smaller minimum. For example, if we have - // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If - // selected tabs have a minimum width of 4 and unselected tabs have a minimum - // width of 1, the above code would set *unselected_width = 2.5, - // *selected_width = 4, which results in a total width of 11.5. Instead, we - // want to set *unselected_width = 2, *selected_width = 4, for a total width - // of 10. - if (tab_count > 1) { - if ((min_unselected_width < min_selected_width) && - (desired_tab_width < min_selected_width)) { - // Unselected width = (total width - selected width) / (num_tabs - 1) - *unselected_width = std::max(static_cast<double>( - available_width - total_offset - min_selected_width) / - static_cast<double>(tab_count - 1), min_unselected_width); - } else if ((min_unselected_width > min_selected_width) && - (desired_tab_width < min_unselected_width)) { - // Selected width = (total width - (unselected width * (num_tabs - 1))) - *selected_width = std::max(available_width - total_offset - - (min_unselected_width * (tab_count - 1)), min_selected_width); - } - } -} - -void TabStrip::ResizeLayoutTabs() { - // We've been called back after the TabStrip has been emptied out (probably - // just prior to the window being destroyed). We need to do nothing here or - // else GetTabAt below will crash. - if (tab_count() == 0) - return; - - // It is critically important that this is unhooked here, otherwise we will - // keep spying on messages forever. - RemoveMessageLoopObserver(); - - in_tab_close_ = false; - available_width_for_tabs_ = -1; - int mini_tab_count = GetMiniTabCount(); - if (mini_tab_count == tab_count()) { - // Only mini-tabs, we know the tab widths won't have changed (all - // mini-tabs have the same width), so there is nothing to do. - return; - } - Tab* first_tab = GetTabAtTabDataIndex(mini_tab_count); - double unselected, selected; - GetDesiredTabWidths(tab_count(), mini_tab_count, &unselected, &selected); - int w = Round(first_tab->IsSelected() ? selected : selected); - - // We only want to run the animation if we're not already at the desired - // size. - if (abs(first_tab->width() - w) > 1) - StartResizeLayoutAnimation(); -} - -void TabStrip::AddMessageLoopObserver() { - if (!mouse_watcher_.get()) { - mouse_watcher_.reset( - new views::MouseWatcher(this, this, - gfx::Insets(0, 0, kTabStripAnimationVSlop, 0))); - } - mouse_watcher_->Start(); -} - -void TabStrip::RemoveMessageLoopObserver() { - mouse_watcher_.reset(NULL); -} - -gfx::Rect TabStrip::GetDropBounds(int drop_index, - bool drop_before, - bool* is_beneath) { - DCHECK(drop_index != -1); - int center_x; - if (drop_index < tab_count()) { - Tab* tab = GetTabAtTabDataIndex(drop_index); - if (drop_before) - center_x = tab->x() - (kTabHOffset / 2); - else - center_x = tab->x() + (tab->width() / 2); - } else { - Tab* last_tab = GetTabAtTabDataIndex(drop_index - 1); - center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); - } - - // Mirror the center point if necessary. - center_x = MirroredXCoordinateInsideView(center_x); - - // Determine the screen bounds. - gfx::Point drop_loc(center_x - drop_indicator_width / 2, - -drop_indicator_height); - ConvertPointToScreen(this, &drop_loc); - gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, - drop_indicator_height); - - // If the rect doesn't fit on the monitor, push the arrow to the bottom. -#if defined(OS_WIN) - gfx::Rect monitor_bounds = win_util::GetMonitorBoundsForRect(drop_bounds); - *is_beneath = (monitor_bounds.IsEmpty() || - !monitor_bounds.Contains(drop_bounds)); -#else - *is_beneath = false; - NOTIMPLEMENTED(); -#endif - if (*is_beneath) - drop_bounds.Offset(0, drop_bounds.height() + height()); - - return drop_bounds; -} - -void TabStrip::UpdateDropIndex(const DropTargetEvent& event) { - // If the UI layout is right-to-left, we need to mirror the mouse - // coordinates since we calculate the drop index based on the - // original (and therefore non-mirrored) positions of the tabs. - const int x = MirroredXCoordinateInsideView(event.x()); - // We don't allow replacing the urls of mini-tabs. - for (int i = GetMiniTabCount(); i < tab_count(); ++i) { - Tab* tab = GetTabAtTabDataIndex(i); - const int tab_max_x = tab->x() + tab->width(); - const int hot_width = tab->width() / 3; - if (x < tab_max_x) { - if (x < tab->x() + hot_width) - SetDropIndex(i, true); - else if (x >= tab_max_x - hot_width) - SetDropIndex(i + 1, true); - else - SetDropIndex(i, false); - return; - } - } - - // The drop isn't over a tab, add it to the end. - SetDropIndex(tab_count(), true); -} - -void TabStrip::SetDropIndex(int tab_data_index, bool drop_before) { - if (tab_data_index == -1) { - if (drop_info_.get()) - drop_info_.reset(NULL); - return; - } - - if (drop_info_.get() && drop_info_->drop_index == tab_data_index && - drop_info_->drop_before == drop_before) { - return; - } - - bool is_beneath; - gfx::Rect drop_bounds = GetDropBounds(tab_data_index, drop_before, - &is_beneath); - - if (!drop_info_.get()) { - drop_info_.reset(new DropInfo(tab_data_index, drop_before, !is_beneath)); - } else { - drop_info_->drop_index = tab_data_index; - drop_info_->drop_before = drop_before; - if (is_beneath == drop_info_->point_down) { - drop_info_->point_down = !is_beneath; - drop_info_->arrow_view->SetImage( - GetDropArrowImage(drop_info_->point_down)); - } - } - - // Reposition the window. Need to show it too as the window is initially - // hidden. - -#if defined(OS_WIN) - drop_info_->arrow_window->SetWindowPos( - HWND_TOPMOST, drop_bounds.x(), drop_bounds.y(), drop_bounds.width(), - drop_bounds.height(), SWP_NOACTIVATE | SWP_SHOWWINDOW); -#else - drop_info_->arrow_window->SetBounds(drop_bounds); - drop_info_->arrow_window->Show(); -#endif -} - -int TabStrip::GetDropEffect(const views::DropTargetEvent& event) { - const int source_ops = event.GetSourceOperations(); - if (source_ops & DragDropTypes::DRAG_COPY) - return DragDropTypes::DRAG_COPY; - if (source_ops & DragDropTypes::DRAG_LINK) - return DragDropTypes::DRAG_LINK; - return DragDropTypes::DRAG_MOVE; -} - -// static -SkBitmap* TabStrip::GetDropArrowImage(bool is_down) { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - is_down ? IDR_TAB_DROP_DOWN : IDR_TAB_DROP_UP); -} - -// TabStrip::DropInfo ---------------------------------------------------------- - -TabStrip::DropInfo::DropInfo(int drop_index, bool drop_before, bool point_down) - : drop_index(drop_index), - drop_before(drop_before), - point_down(point_down) { - arrow_view = new views::ImageView; - arrow_view->SetImage(GetDropArrowImage(point_down)); - -#if defined(OS_WIN) - arrow_window = new views::WidgetWin; - arrow_window->set_window_style(WS_POPUP); - arrow_window->set_window_ex_style(WS_EX_TOPMOST | WS_EX_NOACTIVATE | - WS_EX_LAYERED | WS_EX_TRANSPARENT); -#else - arrow_window = new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP); - arrow_window->MakeTransparent(); -#endif - arrow_window->Init( - NULL, - gfx::Rect(0, 0, drop_indicator_width, drop_indicator_height)); - arrow_window->SetContentsView(arrow_view); -} - -TabStrip::DropInfo::~DropInfo() { - // Close eventually deletes the window, which deletes arrow_view too. - arrow_window->Close(); -} - -/////////////////////////////////////////////////////////////////////////////// - -// Called from: -// - BasicLayout -// - Tab insertion/removal -// - Tab reorder -void TabStrip::GenerateIdealBounds() { - int non_closing_tab_count = 0; - int mini_tab_count = 0; - for (int i = 0; i < tab_count(); ++i) { - BaseTab* tab = base_tab_at_tab_index(i); - if (!tab->closing()) { - ++non_closing_tab_count; - if (tab->data().mini) - mini_tab_count++; - } - } - - double unselected, selected; - GetDesiredTabWidths(non_closing_tab_count, mini_tab_count, &unselected, - &selected); - - current_unselected_width_ = unselected; - current_selected_width_ = selected; - - // NOTE: This currently assumes a tab's height doesn't differ based on - // selected state or the number of tabs in the strip! - int tab_height = Tab::GetStandardSize().height(); - double tab_x = 0; - bool last_was_mini = false; - for (int i = 0; i < tab_count(); ++i) { - Tab* tab = GetTabAtTabDataIndex(i); - if (!tab->closing()) { - double tab_width = unselected; - if (tab->data().mini) { - tab_width = Tab::GetMiniWidth(); - } else { - if (last_was_mini) { - // Give a bigger gap between mini and non-mini tabs. - tab_x += mini_to_non_mini_gap_; - } - if (tab->IsSelected()) - tab_width = selected; - } - double end_of_tab = tab_x + tab_width; - int rounded_tab_x = Round(tab_x); - set_ideal_bounds(i, - gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, - tab_height)); - tab_x = end_of_tab + kTabHOffset; - last_was_mini = tab->data().mini; - } - } - - // Update bounds of new tab button. - int new_tab_x; - int new_tab_y = browser_defaults::kSizeTabButtonToTopOfTabStrip ? - 0 : kNewTabButtonVOffset; - if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && - !in_tab_close_) { - // We're shrinking tabs, so we need to anchor the New Tab button to the - // right edge of the TabStrip's bounds, rather than the right edge of the - // right-most Tab, otherwise it'll bounce when animating. - new_tab_x = width() - newtab_button_bounds_.width(); - } else { - new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; - } - newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); -} - -void TabStrip::StartResizeLayoutAnimation() { - PrepareForAnimation(); - GenerateIdealBounds(); - AnimateToIdealBounds(); -} - -void TabStrip::StartMiniTabAnimation() { - in_tab_close_ = false; - available_width_for_tabs_ = -1; - - PrepareForAnimation(); - - GenerateIdealBounds(); - AnimateToIdealBounds(); -} - -void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { - // The user initiated the close. We want to persist the bounds of all the - // existing tabs, so we manually shift ideal_bounds then animate. - int tab_data_index = ModelIndexToTabIndex(model_index); - DCHECK(tab_data_index != tab_count()); - BaseTab* tab_closing = base_tab_at_tab_index(tab_data_index); - int delta = tab_closing->width() + kTabHOffset; - if (tab_closing->data().mini && model_index + 1 < GetModelCount() && - !GetBaseTabAtModelIndex(model_index + 1)->data().mini) { - delta += mini_to_non_mini_gap_; - } - - for (int i = tab_data_index + 1; i < tab_count(); ++i) { - BaseTab* tab = base_tab_at_tab_index(i); - if (!tab->closing()) { - gfx::Rect bounds = ideal_bounds(i); - bounds.set_x(bounds.x() - delta); - set_ideal_bounds(i, bounds); - } - } - - newtab_button_bounds_.set_x(newtab_button_bounds_.x() - delta); - - PrepareForAnimation(); - - // Mark the tab as closing. - tab_closing->set_closing(true); - - AnimateToIdealBounds(); - - gfx::Rect tab_bounds = tab_closing->bounds(); - if (type() == HORIZONTAL_TAB_STRIP) - tab_bounds.set_width(0); - else - tab_bounds.set_height(0); - bounds_animator().AnimateViewTo(tab_closing, tab_bounds); - - // Register delegate to do cleanup when done, BoundsAnimator takes - // ownership of RemoveTabDelegate. - bounds_animator().SetAnimationDelegate(tab_closing, - CreateRemoveTabDelegate(tab_closing), - true); -} - -void TabStrip::StopAnimating(bool layout) { - if (!IsAnimating()) - return; - - bounds_animator().Cancel(); - - DCHECK(!IsAnimating()); - - if (layout) - DoLayout(); -} - -int TabStrip::GetMiniTabCount() const { - int mini_count = 0; - for (int i = 0; i < tab_count(); ++i) { - if (base_tab_at_tab_index(i)->data().mini) - mini_count++; - else - return mini_count; - } - return mini_count; -} - -int TabStrip::GetAvailableWidthForTabs(Tab* last_tab) const { - return last_tab->x() + last_tab->width(); -} - -bool TabStrip::IsPointInTab(Tab* tab, - const gfx::Point& point_in_tabstrip_coords) { - gfx::Point point_in_tab_coords(point_in_tabstrip_coords); - View::ConvertPointToView(this, tab, &point_in_tab_coords); - return tab->HitTest(point_in_tab_coords); -} diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h index f7ec80fd..4c24f8c 100644 --- a/chrome/browser/views/tabs/tab_strip.h +++ b/chrome/browser/views/tabs/tab_strip.h @@ -6,282 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_ #pragma once -#include "app/animation_container.h" -#include "base/ref_counted.h" -#include "base/timer.h" -#include "chrome/browser/views/tabs/base_tab_strip.h" -#include "gfx/point.h" -#include "gfx/rect.h" -#include "views/controls/button/image_button.h" -#include "views/mouse_watcher.h" - -class Tab; - -namespace views { -class ImageView; -#if defined(OS_LINUX) -class WidgetGtk; -#elif defined(OS_WIN) -class WidgetWin; -#endif -} - -/////////////////////////////////////////////////////////////////////////////// -// -// TabStrip -// -// A View that represents the TabStripModel. The TabStrip has the -// following responsibilities: -// - It implements the TabStripModelObserver interface, and acts as a -// container for Tabs, and is also responsible for creating them. -// - It takes part in Tab Drag & Drop with Tab, TabDragHelper and -// DraggedTab, focusing on tasks that require reshuffling other tabs -// in response to dragged tabs. -// -/////////////////////////////////////////////////////////////////////////////// -class TabStrip : public BaseTabStrip, - public views::ButtonListener, - public views::MouseWatcherListener { - public: - explicit TabStrip(TabStripController* controller); - virtual ~TabStrip(); - - // Creates the new tab button. - void InitTabStripButtons(); - - // Returns the bounds of the new tab button. - gfx::Rect GetNewTabButtonBounds(); - - // MouseWatcherListener overrides: - virtual void MouseMovedOutOfView(); - - // BaseTabStrip implementation: - virtual int GetPreferredHeight(); - virtual void SetBackgroundOffset(const gfx::Point& offset); - virtual bool IsPositionInWindowCaption(const gfx::Point& point); - virtual void SetDraggedTabBounds(int tab_index, - const gfx::Rect& tab_bounds); - virtual TabStrip* AsTabStrip(); - virtual void PrepareForCloseAt(int model_index); - virtual void RemoveTabAt(int model_index); - virtual void SelectTabAt(int old_model_index, int new_model_index); - virtual void TabTitleChangedNotLoading(int model_index); - virtual void StartHighlight(int model_index); - virtual void StopAllHighlighting(); - virtual BaseTab* CreateTabForDragging(); - - // views::View overrides: - virtual void PaintChildren(gfx::Canvas* canvas); - virtual views::View* GetViewByID(int id) const; - virtual gfx::Size GetPreferredSize(); - // NOTE: the drag and drop methods are invoked from FrameView. This is done to - // allow for a drop region that extends outside the bounds of the TabStrip. - virtual void OnDragEntered(const views::DropTargetEvent& event); - virtual int OnDragUpdated(const views::DropTargetEvent& event); - virtual void OnDragExited(); - virtual int OnPerformDrop(const views::DropTargetEvent& event); - virtual AccessibilityTypes::Role GetAccessibleRole(); - virtual views::View* GetViewForPoint(const gfx::Point& point); - virtual void OnThemeChanged(); - - protected: - // BaseTabStrip overrides: - virtual BaseTab* CreateTab(); - virtual void StartInsertTabAnimation(int model_index, bool foreground); - virtual void StartMoveTabAnimation(); - virtual void AnimateToIdealBounds(); - virtual bool ShouldHighlightCloseButtonAfterRemove(); - virtual void DoLayout(); - - // views::View implementation: - virtual void ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child); - - // TabController overrides. - virtual bool IsTabSelected(const BaseTab* btr) const; - - // views::ButtonListener implementation: - virtual void ButtonPressed(views::Button* sender, const views::Event& event); - - // Horizontal gap between mini and non-mini-tabs. - static const int mini_to_non_mini_gap_; - - private: - friend class DraggedTabController; - - // Used during a drop session of a url. Tracks the position of the drop as - // well as a window used to highlight where the drop occurs. - struct DropInfo { - DropInfo(int index, bool drop_before, bool paint_down); - ~DropInfo(); - - // Index of the tab to drop on. If drop_before is true, the drop should - // occur between the tab at drop_index - 1 and drop_index. - // WARNING: if drop_before is true it is possible this will == tab_count, - // which indicates the drop should create a new tab at the end of the tabs. - int drop_index; - bool drop_before; - - // Direction the arrow should point in. If true, the arrow is displayed - // above the tab and points down. If false, the arrow is displayed beneath - // the tab and points up. - bool point_down; - - // Renders the drop indicator. - // TODO(beng): should be views::Widget. -#if defined(OS_WIN) - views::WidgetWin* arrow_window; -#else - views::WidgetGtk* arrow_window; -#endif - views::ImageView* arrow_view; - - private: - DISALLOW_COPY_AND_ASSIGN(DropInfo); - }; - - void Init(); - - // Set the images for the new tab button. - void LoadNewTabButtonImage(); - - // Retrieves the Tab at the specified index. Remember, the specified index - // is in terms of tab_data, *not* the model. - Tab* GetTabAtTabDataIndex(int tab_data_index) const; - - // Returns the tab at the specified index. If a remove animation is on going - // and the index is >= the index of the tab being removed, the index is - // incremented. While a remove operation is on going the indices of the model - // do not line up with the indices of the view. This method adjusts the index - // accordingly. - // - // Use this instead of GetTabAtTabDataIndex if the index comes from the model. - Tab* GetTabAtModelIndex(int model_index) const; - - // Returns the number of mini-tabs. - int GetMiniTabCount() const; - - // -- Tab Resize Layout ----------------------------------------------------- - - // Returns the exact (unrounded) current width of each tab. - void GetCurrentTabWidths(double* unselected_width, - double* selected_width) const; - - // Returns the exact (unrounded) desired width of each tab, based on the - // desired strip width and number of tabs. If - // |width_of_tabs_for_mouse_close_| is nonnegative we use that value in - // calculating the desired strip width; otherwise we use the current width. - // |mini_tab_count| gives the number of mini-tabs and |tab_count| the number - // of mini and non-mini-tabs. - void GetDesiredTabWidths(int tab_count, - int mini_tab_count, - double* unselected_width, - double* selected_width) const; - - // Perform an animated resize-relayout of the TabStrip immediately. - void ResizeLayoutTabs(); - - // Ensure that the message loop observer used for event spying is added and - // removed appropriately so we can tell when to resize layout the tab strip. - void AddMessageLoopObserver(); - void RemoveMessageLoopObserver(); - - // -- Link Drag & Drop ------------------------------------------------------ - - // Returns the bounds to render the drop at, in screen coordinates. Sets - // |is_beneath| to indicate whether the arrow is beneath the tab, or above - // it. - gfx::Rect GetDropBounds(int drop_index, bool drop_before, bool* is_beneath); - - // Updates the location of the drop based on the event. - void UpdateDropIndex(const views::DropTargetEvent& event); - - // Sets the location of the drop, repainting as necessary. - void SetDropIndex(int tab_data_index, bool drop_before); - - // Returns the drop effect for dropping a URL on the tab strip. This does - // not query the data in anyway, it only looks at the source operations. - int GetDropEffect(const views::DropTargetEvent& event); - - // Returns the image to use for indicating a drop on a tab. If is_down is - // true, this returns an arrow pointing down. - static SkBitmap* GetDropArrowImage(bool is_down); - - // -- Animations ------------------------------------------------------------ - - // Generates the ideal bounds of the TabStrip when all Tabs have finished - // animating to their desired position/bounds. This is used by the standard - // Layout method and other callers like the DraggedTabController that need - // stable representations of Tab positions. - void GenerateIdealBounds(); - - // Starts various types of TabStrip animations. - void StartResizeLayoutAnimation(); - void StartMoveTabAnimation(int from_model_index, - int to_model_index); - void StartMiniTabAnimation(); - void StartMouseInitiatedRemoveTabAnimation(int model_index); - - // Stops any ongoing animations. If |layout| is true and an animation is - // ongoing this does a layout. - virtual void StopAnimating(bool layout); - - // Calculates the available width for tabs, assuming a Tab is to be closed. - int GetAvailableWidthForTabs(Tab* last_tab) const; - - // Returns true if the specified point in TabStrip coords is within the - // hit-test region of the specified Tab. - bool IsPointInTab(Tab* tab, const gfx::Point& point_in_tabstrip_coords); - - // -- Member Variables ------------------------------------------------------ - - // The "New Tab" button. - views::ImageButton* newtab_button_; - - // Ideal bounds of the new tab button. - gfx::Rect newtab_button_bounds_; - - // The current widths of various types of tabs. We save these so that, as - // users close tabs while we're holding them at the same size, we can lay out - // tabs exactly and eliminate the "pixel jitter" we'd get from just leaving - // them all at their existing, rounded widths. - double current_unselected_width_; - double current_selected_width_; - - // If this value is nonnegative, it is used in GetDesiredTabWidths() to - // calculate how much space in the tab strip to use for tabs. Most of the - // time this will be -1, but while we're handling closing a tab via the mouse, - // we'll set this to the edge of the last tab before closing, so that if we - // are closing the last tab and need to resize immediately, we'll resize only - // back to this width, thus once again placing the last tab under the mouse - // cursor. - int available_width_for_tabs_; - - // True if PrepareForCloseAt has been invoked. When true remove animations - // preserve current tab bounds. - bool in_tab_close_; - - // The size of the new tab button must be hardcoded because we need to be - // able to lay it out before we are able to get its image from the - // ThemeProvider. It also makes sense to do this, because the size of the - // new tab button should not need to be calculated dynamically. - static const int kNewTabButtonWidth = 28; - static const int kNewTabButtonHeight = 18; - - // Valid for the lifetime of a drag over us. - scoped_ptr<DropInfo> drop_info_; - - // To ensure all tabs pulse at the same time they share the same animation - // container. This is that animation container. - scoped_refptr<AnimationContainer> animation_container_; - - // Used for stage 1 of new tab animation. - base::OneShotTimer<TabStrip> new_tab_timer_; - - scoped_ptr<views::MouseWatcher> mouse_watcher_; - - DISALLOW_COPY_AND_ASSIGN(TabStrip); -}; +#include "chrome/browser/ui/views/tabs/tab_strip.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_H_ + diff --git a/chrome/browser/views/tabs/tab_strip_controller.h b/chrome/browser/views/tabs/tab_strip_controller.h index bd52452..b0c7be9 100644 --- a/chrome/browser/views/tabs/tab_strip_controller.h +++ b/chrome/browser/views/tabs/tab_strip_controller.h @@ -6,68 +6,8 @@ #define CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_ #pragma once -class BaseTab; -class BaseTabStrip; -class GURL; - -namespace gfx { -class Point; -} - -// Model/Controller for the TabStrip. -// NOTE: All indices used by this class are in model coordinates. -class TabStripController { - public: - virtual ~TabStripController() {} - - // Returns the number of tabs in the model. - virtual int GetCount() const = 0; - - // Returns true if |index| is a valid model index. - virtual bool IsValidIndex(int index) const = 0; - - // Returns the selected index, in terms of the model. - virtual int GetSelectedIndex() const = 0; - - // Returns true if the selected index is selected. - virtual bool IsTabSelected(int index) const = 0; - - // Returns true if the selected index is pinned. - virtual bool IsTabPinned(int index) const = 0; - - // Returns true if the selected index is closeable. - virtual bool IsTabCloseable(int index) const = 0; - - // Returns true if the selected index is the new tab page. - virtual bool IsNewTabPage(int index) const = 0; - - // Select the tab at the specified index in the model. - virtual void SelectTab(int index) = 0; - - // Closes the tab at the specified index in the model. - virtual void CloseTab(int index) = 0; - - // Shows a context menu for the tab at the specified point in screen coords. - virtual void ShowContextMenu(BaseTab* tab, const gfx::Point& p) = 0; - - // Updates the loading animations of all the tabs. - virtual void UpdateLoadingAnimations() = 0; - - // Returns true if the associated TabStrip's delegate supports tab moving or - // detaching. Used by the Frame to determine if dragging on the Tab - // itself should move the window in cases where there's only one - // non drag-able Tab. - virtual int HasAvailableDragActions() const = 0; - - // Performans a drop at the specified location. - virtual void PerformDrop(bool drop_before, int index, const GURL& url) = 0; - - // Return true if this tab strip is compatible with the provided tab strip. - // Compatible tab strips can transfer tabs during drag and drop. - virtual bool IsCompatibleWith(BaseTabStrip* other) const = 0; - - // Creates the new tab. - virtual void CreateNewTab() = 0; -}; +#include "chrome/browser/ui/views/tabs/tab_strip_controller.h" +// TODO(beng): remove this file once all includes have been updated. #endif // CHROME_BROWSER_VIEWS_TABS_TAB_STRIP_CONTROLLER_H_ + |