summaryrefslogtreecommitdiffstats
path: root/chrome/browser/tabs
diff options
context:
space:
mode:
authorbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-12 22:44:06 +0000
committerbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-12 22:44:06 +0000
commit3146282c2250c51569d971234fbc9756b4d7a2d4 (patch)
tree0f9f418993163cd7a67955d10e89928b28787978 /chrome/browser/tabs
parent5db2a6ed0d09ef82cf84ba2677ecfcdff6192c79 (diff)
downloadchromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.zip
chromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.tar.gz
chromium_src-3146282c2250c51569d971234fbc9756b4d7a2d4.tar.bz2
Move View components of the Browser's tab strip into the browser_views project, and into the views/ subdirectory on disk.
B=2198 Review URL: http://codereview.chromium.org/3020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2140 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/tabs')
-rw-r--r--chrome/browser/tabs/dragged_tab_controller.cc798
-rw-r--r--chrome/browser/tabs/dragged_tab_controller.h286
-rw-r--r--chrome/browser/tabs/dragged_tab_view.cc244
-rw-r--r--chrome/browser/tabs/dragged_tab_view.h119
-rw-r--r--chrome/browser/tabs/hwnd_photobooth.cc159
-rw-r--r--chrome/browser/tabs/hwnd_photobooth.h62
-rw-r--r--chrome/browser/tabs/tab.cc241
-rw-r--r--chrome/browser/tabs/tab.h125
-rw-r--r--chrome/browser/tabs/tab_dragging_test.cc507
-rw-r--r--chrome/browser/tabs/tab_renderer.cc691
-rw-r--r--chrome/browser/tabs/tab_renderer.h174
-rw-r--r--chrome/browser/tabs/tab_strip.cc1524
-rw-r--r--chrome/browser/tabs/tab_strip.h373
13 files changed, 0 insertions, 5303 deletions
diff --git a/chrome/browser/tabs/dragged_tab_controller.cc b/chrome/browser/tabs/dragged_tab_controller.cc
deleted file mode 100644
index 80cbe65..0000000
--- a/chrome/browser/tabs/dragged_tab_controller.cc
+++ /dev/null
@@ -1,798 +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/tabs/dragged_tab_controller.h"
-
-#include <math.h>
-
-#include "chrome/browser/browser_window.h"
-#include "chrome/browser/frame_util.h"
-#include "chrome/browser/tab_contents.h"
-#include "chrome/browser/tabs/dragged_tab_view.h"
-#include "chrome/browser/tabs/hwnd_photobooth.h"
-#include "chrome/browser/tabs/tab.h"
-#include "chrome/browser/tabs/tab_strip.h"
-#include "chrome/browser/web_contents.h"
-#include "chrome/views/event.h"
-#include "chrome/views/root_view.h"
-#include "skia/include/SkBitmap.h"
-
-static const int kHorizontalMoveThreshold = 16; // pixels
-
-namespace {
-
-///////////////////////////////////////////////////////////////////////////////
-// WindowFinder
-// A WindowForPoint facility that can ignore 2 provided window HWNDs.
-//
-class WindowFinder {
- public:
- static HWND WindowForPoint(const gfx::Point& screen_point, HWND ignore1) {
- WindowFinder instance(screen_point, ignore1);
- return instance.GetResult();
- }
- private:
- WindowFinder(const gfx::Point& screen_point, HWND ignore1)
- : screen_point_(screen_point.ToPOINT()),
- ignore1_(ignore1),
- result_(NULL) {
- }
-
- static BOOL CALLBACK WindowEnumProc(HWND hwnd, LPARAM lParam) {
- WindowFinder* wf = reinterpret_cast<WindowFinder*>(lParam);
- if (hwnd == wf->ignore1_)
- return true;
-
- if (::IsWindowVisible(hwnd)) {
- CRect r;
- ::GetWindowRect(hwnd, &r);
- if (r.PtInRect(wf->screen_point_)) {
- // We always deal with the root HWND.
- wf->result_ = GetAncestor(hwnd, GA_ROOT);
- return FALSE;
- }
- }
- return TRUE;
- }
-
- HWND GetResult() {
- EnumThreadWindows(GetCurrentThreadId(), WindowEnumProc,
- reinterpret_cast<LPARAM>(this));
- return result_;
- }
-
- POINT screen_point_;
- HWND ignore1_;
- HWND result_;
-
- DISALLOW_EVIL_CONSTRUCTORS(WindowFinder);
-};
-
-gfx::Point ConvertScreenPointToTabStripPoint(TabStrip* tabstrip,
- const gfx::Point& screen_point) {
- CPoint tabstrip_topleft(0, 0);
- ChromeViews::View::ConvertPointToScreen(tabstrip, &tabstrip_topleft);
- return gfx::Point(screen_point.x() - tabstrip_topleft.x,
- screen_point.y() - tabstrip_topleft.y);
-}
-
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabController, public:
-
-DraggedTabController::DraggedTabController(Tab* source_tab,
- TabStrip* source_tabstrip)
- : dragged_contents_(NULL),
- original_delegate_(NULL),
- source_tab_(source_tab),
- source_tabstrip_(source_tabstrip),
- source_model_index_(source_tabstrip->GetIndexOfTab(source_tab)),
- attached_tabstrip_(source_tabstrip),
- old_focused_view_(NULL),
- in_destructor_(false),
- last_move_screen_x_(0) {
- ChangeDraggedContents(
- source_tabstrip_->model()->GetTabContentsAt(source_model_index_));
- // Listen for Esc key presses.
- MessageLoopForUI::current()->AddObserver(this);
-}
-
-DraggedTabController::~DraggedTabController() {
- in_destructor_ = true;
- CleanUpSourceTab();
- MessageLoopForUI::current()->RemoveObserver(this);
- ChangeDraggedContents(NULL); // This removes our observer.
-}
-
-void DraggedTabController::CaptureDragInfo(const gfx::Point& mouse_offset) {
- start_screen_point_ = GetCursorScreenPoint();
- mouse_offset_ = mouse_offset;
-}
-
-void DraggedTabController::Drag() {
- // Before we get to dragging anywhere, ensure that we consider ourselves
- // attached to the source tabstrip.
- if (source_tab_->IsVisible() && CanStartDrag())
- Attach(source_tabstrip_, gfx::Point());
-
- if (!source_tab_->IsVisible()) {
- SaveFocus();
- ContinueDragging();
- }
-}
-
-void DraggedTabController::EndDrag(bool canceled) {
- EndDragImpl(canceled ? CANCELED : NORMAL);
-}
-
-Tab* DraggedTabController::GetDragSourceTabForContents(
- TabContents* contents) const {
- if (attached_tabstrip_ == source_tabstrip_)
- return contents == dragged_contents_ ? source_tab_ : NULL;
- return NULL;
-}
-
-bool DraggedTabController::IsDragSourceTab(Tab* tab) const {
- return source_tab_ == tab;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabController, PageNavigator implementation:
-
-void DraggedTabController::OpenURLFromTab(
- TabContents* source,
- const GURL& url,
- WindowOpenDisposition disposition,
- PageTransition::Type transition,
- const std::string& override_encoding) {
- if (original_delegate_) {
- if (disposition == CURRENT_TAB)
- disposition = NEW_WINDOW;
-
- original_delegate_->OpenURLFromTab(source, url, disposition, transition,
- override_encoding);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabController, TabContentsDelegate implementation:
-
-void DraggedTabController::NavigationStateChanged(const TabContents* source,
- unsigned changed_flags) {
- if (view_.get())
- view_->Update();
-}
-
-void DraggedTabController::ReplaceContents(TabContents* source,
- TabContents* new_contents) {
- DCHECK(dragged_contents_ == source);
- source->set_delegate(NULL);
- new_contents->set_delegate(this);
-
- // If we're attached to a TabStrip, we need to tell the TabStrip that this
- // TabContents was replaced.
- if (attached_tabstrip_ && attached_tabstrip_->model() && dragged_contents_) {
- int index =
- attached_tabstrip_->model()->GetIndexOfTabContents(dragged_contents_);
- if (index != TabStripModel::kNoTab)
- attached_tabstrip_->model()->ReplaceTabContentsAt(index, new_contents);
- }
-
- // Update our internal state.
- ChangeDraggedContents(new_contents);
-
- if (view_.get())
- view_->Update();
-}
-
-void DraggedTabController::AddNewContents(TabContents* source,
- TabContents* new_contents,
- WindowOpenDisposition disposition,
- const gfx::Rect& initial_pos,
- bool user_gesture) {
- // 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 (disposition == CURRENT_TAB) {
- ReplaceContents(source, new_contents);
- } else if (original_delegate_) {
- original_delegate_->AddNewContents(source, new_contents, disposition,
- initial_pos, user_gesture);
- }
-}
-
-void DraggedTabController::ActivateContents(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...
-}
-
-bool DraggedTabController::IsPopup(TabContents* source) {
- return false;
-}
-
-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 == NOTIFY_TAB_CONTENTS_DESTROYED);
- DCHECK(Source<TabContents>(source).ptr() == dragged_contents_);
- EndDragImpl(TAB_DESTROYED);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabController, MessageLoop::Observer implementation:
-
-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);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabController, private:
-
-void DraggedTabController::InitWindowCreatePoint() {
- CPoint mouse_offset_cpoint(mouse_offset_.x(), mouse_offset_.y());
- Tab* first_tab = attached_tabstrip_->GetTabAt(0);
- ChromeViews::View::ConvertPointToViewContainer(first_tab,
- &mouse_offset_cpoint);
- window_create_point_.SetPoint(mouse_offset_cpoint.x, mouse_offset_cpoint.y);
-}
-
-gfx::Point DraggedTabController::GetWindowCreatePoint() const {
- POINT pt;
- GetCursorPos(&pt);
- return gfx::Point(pt.x - window_create_point_.x(),
- pt.y - window_create_point_.y());
-}
-
-void DraggedTabController::ChangeDraggedContents(TabContents* new_contents) {
- if (dragged_contents_) {
- NotificationService::current()->RemoveObserver(this,
- NOTIFY_TAB_CONTENTS_DESTROYED,
- Source<TabContents>(dragged_contents_));
- }
- dragged_contents_ = new_contents;
- if (dragged_contents_) {
- NotificationService::current()->AddObserver(this,
- NOTIFY_TAB_CONTENTS_DESTROYED,
- Source<TabContents>(dragged_contents_));
- }
-}
-
-void DraggedTabController::SaveFocus() {
- if (!old_focused_view_) {
- old_focused_view_ = source_tab_->GetRootView()->GetFocusedView();
- source_tab_->GetRootView()->FocusView(source_tab_);
- }
-}
-
-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() {
- EnsureDraggedView();
-
- // 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();
-
- // 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.
- TabStrip* target_tabstrip = GetTabStripForPoint(screen_point);
- if (target_tabstrip != attached_tabstrip_) {
- if (target_tabstrip) {
- // We may receive this event before we're fully detached from the source,
- // we check for that and force a detach now.
- if (attached_tabstrip_)
- Detach();
- Attach(target_tabstrip, screen_point);
- } else {
- Detach();
- }
- }
- MoveTab(screen_point);
-}
-
-void DraggedTabController::MoveTab(const gfx::Point& screen_point) {
- gfx::Point dragged_view_point = GetDraggedViewPoint(screen_point);
-
- if (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;
- attached_tabstrip_->GetCurrentTabWidths(&unselected, &selected);
- double ratio = unselected / Tab::GetStandardSize().width();
- int 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(screen_point.x() - last_move_screen_x_) > threshold) {
- TabStripModel* attached_model = attached_tabstrip_->model();
- int from_index =
- attached_model->GetIndexOfTabContents(dragged_contents_);
- gfx::Rect bounds = GetDraggedViewTabStripBounds(dragged_view_point);
- int to_index = GetInsertionIndexForDraggedBounds(bounds);
- to_index = NormalizeIndexToAttachedTabStrip(to_index);
- if (from_index != to_index) {
- last_move_screen_x_ = screen_point.x();
- attached_model->MoveTabContentsAt(from_index, to_index);
- }
- }
- }
- // Move the View. There are no changes to the model if we're detached.
- view_->MoveTo(dragged_view_point);
-}
-
-TabStrip* DraggedTabController::GetTabStripForPoint(
- const gfx::Point& screen_point) const {
- HWND dragged_hwnd = view_->GetViewContainer()->GetHWND();
- HWND other_hwnd = WindowFinder::WindowForPoint(screen_point, dragged_hwnd);
- if (!other_hwnd)
- return NULL;
-
- BrowserWindow* other_frame = FrameUtil::GetBrowserWindowForHWND(other_hwnd);
- if (other_frame) {
- TabStrip* other_tabstrip = other_frame->GetTabStrip();
- if (!other_tabstrip->IsCompatibleWith(source_tabstrip_))
- return NULL;
- return GetTabStripIfItContains(other_tabstrip, screen_point);
- }
- return NULL;
-}
-
-TabStrip* DraggedTabController::GetTabStripIfItContains(
- TabStrip* tabstrip, const gfx::Point& screen_point) const {
- static const int kVerticalDetachMagnetism = 15;
- // Make sure the specified screen point is actually within the bounds of the
- // specified tabstrip...
- gfx::Rect tabstrip_bounds = GetViewScreenBounds(tabstrip);
- 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;
- }
- }
- return NULL;
-}
-
-void DraggedTabController::Attach(TabStrip* attached_tabstrip,
- const gfx::Point& screen_point) {
- attached_tabstrip_ = attached_tabstrip;
- InitWindowCreatePoint();
- attached_tabstrip_->GenerateIdealBounds();
-
- // We don't need the photo-booth while we're attached.
- photobooth_.reset(NULL);
-
- Tab* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
-
- // Update the View first, so we can ask it for its bounds and determine
- // where to insert the hidden Tab.
-
- // If this is the first time Attach is called for this drag, we're attaching
- // to the source TabStrip, and we should assume the tab count already
- // includes this Tab since we haven't been detached yet. If we don't do this,
- // the dragged representation will be a different size to others in the
- // TabStrip.
- int tab_count = attached_tabstrip_->GetTabCount();
- if (!tab)
- ++tab_count;
- double unselected_width, selected_width = 0;
- attached_tabstrip_->GetDesiredTabWidths(tab_count, &unselected_width,
- &selected_width);
- EnsureDraggedView();
- view_->Attach(static_cast<int>(selected_width));
-
- 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_->DidCaptureContents();
-
- // We need to ask the TabStrip we're attached to to ensure that the ideal
- // bounds for all its tabs are correctly generated, because the calculation
- // in GetInsertionIndexForDraggedBounds needs them to be to figure out the
- // appropriate insertion index.
- attached_tabstrip_->GenerateIdealBounds();
-
- // 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_x_ = screen_point.x();
-
- // 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);
- index = std::max(std::min(index, attached_tabstrip_->model()->count()), 0);
- attached_tabstrip_->model()->InsertTabContentsAt(index, dragged_contents_,
- true, false);
-
- tab = GetTabMatchingDraggedContents(attached_tabstrip_);
- }
- DCHECK(tab); // We should now have a tab.
- tab->SetVisible(false);
-
- // Move the corresponding window to the front.
- attached_tabstrip_->GetViewContainer()->MoveToFront(true);
-}
-
-void DraggedTabController::Detach() {
- // Prevent the TabContents' HWND from being hidden by any of the model
- // operations performed during the drag.
- dragged_contents_->WillCaptureContents();
-
- // Update the Model.
- TabStripModel* attached_model = attached_tabstrip_->model();
- int index = attached_model->GetIndexOfTabContents(dragged_contents_);
- if (index >= 0 && index < attached_model->count()) {
- attached_model->DetachTabContentsAt(index);
- attached_tabstrip_->SchedulePaint();
- }
-
- // 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(new HWNDPhotobooth(dragged_contents_->GetContainerHWND()));
-
- // Update the View.
- view_->Detach(photobooth_.get());
-
- // 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);
-
- attached_tabstrip_ = NULL;
-}
-
-int DraggedTabController::GetInsertionIndexForDraggedBounds(
- const gfx::Rect& dragged_bounds) const {
- int right_tab_x = 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));
-
- for (int i = 0; i < attached_tabstrip_->GetTabCount(); ++i) {
- gfx::Rect ideal_bounds = attached_tabstrip_->GetIdealBounds(i);
- 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()) {
- return i + 1;
- } else if (adjusted_bounds.x() >= left_half.x() &&
- adjusted_bounds.x() < left_half.right()) {
- return i;
- }
- }
- if (adjusted_bounds.right() > right_tab_x)
- return attached_tabstrip_->model()->count();
- return TabStripModel::kNoTab;
-}
-
-gfx::Rect DraggedTabController::GetDraggedViewTabStripBounds(
- const gfx::Point& screen_point) {
- gfx::Point client_point =
- ConvertScreenPointToTabStripPoint(attached_tabstrip_, screen_point);
- gfx::Size view_size = view_->attached_tab_size();
- return gfx::Rect(client_point.x(), client_point.y(),
- view_size.width(), view_size.height());
-}
-
-gfx::Point DraggedTabController::GetDraggedViewPoint(
- const gfx::Point& screen_point) {
- int x = screen_point.x() - mouse_offset_.x();
- int y = screen_point.y() - mouse_offset_.y();
-
- // If we're not attached, we just use x and y from above.
- if (attached_tabstrip_) {
- gfx::Rect tabstrip_bounds = GetViewScreenBounds(attached_tabstrip_);
- // Snap the dragged Tab to the TabStrip if we are attached, detaching
- // only when the mouse position (screen_point) exceeds the screen bounds
- // of the TabStrip.
- if (x < tabstrip_bounds.x() && screen_point.x() >= tabstrip_bounds.x())
- x = tabstrip_bounds.x();
-
- gfx::Size tab_size = view_->attached_tab_size();
- int vertical_drag_magnetism = tab_size.height() * 2;
- int vertical_detach_point = tabstrip_bounds.y() - vertical_drag_magnetism;
- if (y < tabstrip_bounds.y() && screen_point.y() >= vertical_detach_point)
- y = tabstrip_bounds.y();
-
- // Make sure the Tab can't be dragged off the right side of the TabStrip
- // unless the mouse pointer passes outside the bounds of the strip by
- // clamping the position of the dragged window to the tabstrip width less
- // the width of one tab until the mouse pointer (screen_point) exceeds the
- // screen bounds of the TabStrip.
- int max_x = tabstrip_bounds.right() - tab_size.width();
- int max_y = tabstrip_bounds.bottom() - tab_size.height();
- if (x > max_x && screen_point.x() <= tabstrip_bounds.right())
- x = max_x;
- if (y > max_y && screen_point.y() <=
- (tabstrip_bounds.bottom() + vertical_drag_magnetism)) {
- y = max_y;
- }
- }
- return gfx::Point(x, y);
-}
-
-
-Tab* DraggedTabController::GetTabMatchingDraggedContents(
- TabStrip* tabstrip) const {
- int index = tabstrip->model()->GetIndexOfTabContents(dragged_contents_);
- return index == TabStripModel::kNoTab ? NULL : tabstrip->GetTabAt(index);
-}
-
-void DraggedTabController::EndDragImpl(EndDragType type) {
- bool destroy_now = true;
- if (type != TAB_DESTROYED) {
- // We only finish up the drag if we were actually dragging. If we never
- // constructed a view, the user just clicked and released and didn't move the
- // mouse enough to trigger a drag.
- if (view_.get()) {
- RestoreFocus();
- if (type == CANCELED) {
- RevertDrag();
- } else {
- destroy_now = CompleteDrag();
- }
- }
- } 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;
- attached_tabstrip_ = NULL;
- }
- // If we're not destroyed now, we'll be destroyed asynchronously later.
- if (destroy_now)
- source_tabstrip_->DestroyDragController();
-}
-
-void DraggedTabController::RevertDrag() {
- // We save this here because code below will modify |attached_tabstrip_|.
- bool restore_frame = attached_tabstrip_ != source_tabstrip_;
- if (attached_tabstrip_) {
- int index = attached_tabstrip_->model()->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.
- attached_tabstrip_->model()->DetachTabContentsAt(index);
- // TODO(beng): (Cleanup) seems like we should use Attach() for this
- // somehow.
- attached_tabstrip_ = source_tabstrip_;
- source_tabstrip_->model()->InsertTabContentsAt(source_model_index_,
- dragged_contents_, true, false);
- } else {
- // The Tab was moved within the TabStrip where the drag was initiated.
- // Move it back to the starting location.
- source_tabstrip_->model()->MoveTabContentsAt(index, source_model_index_);
- }
- } 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.
- source_tabstrip_->model()->InsertTabContentsAt(source_model_index_,
- dragged_contents_, true, false);
- }
- // 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()) {
- HWND frame_hwnd = source_tabstrip_->GetViewContainer()->GetHWND();
- MoveWindow(frame_hwnd, restore_bounds_.x(), restore_bounds_.y(),
- restore_bounds_.width(), restore_bounds_.height(), TRUE);
- }
- }
- source_tab_->SetVisible(true);
-}
-
-bool DraggedTabController::CompleteDrag() {
- bool destroy_immediately = true;
- if (attached_tabstrip_) {
- // We don't need to do anything other than make the Tab visible again,
- // since the dragged View is going away.
- Tab* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
- view_->AnimateToBounds(
- GetViewScreenBounds(tab),
- NewCallback(this, &DraggedTabController::OnAnimateToBoundsComplete));
- destroy_immediately = false;
- } else {
- // Compel the model to construct a new window for the detached TabContents.
- source_tabstrip_->model()->TearOffTabContents(
- dragged_contents_,
- GetWindowCreatePoint());
- CleanUpHiddenFrame();
- }
-
- return destroy_immediately;
-}
-
-void DraggedTabController::EnsureDraggedView() {
- if (!view_.get()) {
- RECT wr;
- GetWindowRect(dragged_contents_->GetContainerHWND(), &wr);
-
- view_.reset(new DraggedTabView(dragged_contents_, mouse_offset_,
- gfx::Size(wr.right - wr.left, wr.bottom - wr.top)));
- }
-}
-
-gfx::Point DraggedTabController::GetCursorScreenPoint() const {
- POINT pt;
- GetCursorPos(&pt);
- return gfx::Point(pt);
-}
-
-gfx::Rect DraggedTabController::GetViewScreenBounds(
- ChromeViews::View* view) const {
- CPoint view_topleft(0, 0);
- ChromeViews::View::ConvertPointToScreen(view, &view_topleft);
- CRect view_screen_bounds;
- view->GetLocalBounds(&view_screen_bounds, true);
- view_screen_bounds.OffsetRect(view_topleft);
- return gfx::Rect(view_screen_bounds);
-}
-
-int DraggedTabController::NormalizeIndexToAttachedTabStrip(int index) const {
- DCHECK(attached_tabstrip_) << "Can only be called when attached!";
- TabStripModel* attached_model = attached_tabstrip_->model();
- if (index >= attached_model->count())
- return attached_model->count() - 1;
- if (index == TabStripModel::kNoTab)
- return 0;
- return index;
-}
-
-void DraggedTabController::HideFrame() {
- // 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_->GetViewContainer()->GetHWND();
- 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);
-}
-
-void DraggedTabController::CleanUpHiddenFrame() {
- // If the model we started dragging from is now empty, we must ask the
- // delegate to close the frame.
- if (source_tabstrip_->model()->empty())
- source_tabstrip_->model()->delegate()->CloseFrameAfterDragSession();
-}
-
-void DraggedTabController::CleanUpSourceTab() {
- // If we were attached to the source TabStrip, source Tab will be in use
- // as the Tab. If we were detached or attached to another TabStrip, we can
- // safely remove this item and delete it now.
- if (attached_tabstrip_ != source_tabstrip_) {
- source_tabstrip_->DestroyDraggedSourceTab(source_tab_);
- source_tab_ = NULL;
- }
-}
-
-void DraggedTabController::OnAnimateToBoundsComplete() {
- // Sometimes, for some reason, in automation we can be called back on a
- // detach even though we aren't attached to a TabStrip. Guard against that.
- if (attached_tabstrip_) {
- Tab* tab = GetTabMatchingDraggedContents(attached_tabstrip_);
- if (tab)
- tab->SetVisible(true);
- }
- CleanUpHiddenFrame();
-
- if (!in_destructor_)
- source_tabstrip_->DestroyDragController();
-}
-
diff --git a/chrome/browser/tabs/dragged_tab_controller.h b/chrome/browser/tabs/dragged_tab_controller.h
deleted file mode 100644
index 031a6ed..0000000
--- a/chrome/browser/tabs/dragged_tab_controller.h
+++ /dev/null
@@ -1,286 +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.
-
-#ifndef CHROME_BROWSER_TABS_DRAGGED_TAB_CONTROLLER_H_
-#define CHROME_BROWSER_TABS_DRAGGED_TAB_CONTROLLER_H_
-
-#include "base/gfx/rect.h"
-#include "base/message_loop.h"
-#include "chrome/browser/tab_contents_delegate.h"
-#include "chrome/browser/tabs/tab_renderer.h"
-#include "chrome/common/notification_service.h"
-
-namespace ChromeViews {
-class MouseEvent;
-class View;
-}
-class DraggedTabView;
-class HWNDPhotobooth;
-class SkBitmap;
-class Tab;
-class TabStrip;
-class TabStripModel;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// 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(Tab* source_tab, TabStrip* source_tabstrip);
- virtual ~DraggedTabController();
-
- // Capture information needed to be used during a drag session for this
- // controller's associated source Tab and TabStrip. |mouse_offset| is the
- // distance of the mouse pointer from the Tab's origin.
- void CaptureDragInfo(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);
-
- // Retrieve the source Tab if the TabContents specified matches the one being
- // dragged by this controller, or NULL if the specified TabContents is not
- // the same as the one being dragged.
- Tab* GetDragSourceTabForContents(TabContents* contents) const;
-
- // Returns true if the specified Tab matches the Tab being dragged.
- bool IsDragSourceTab(Tab* tab) const;
-
- private:
- // 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,
- WindowOpenDisposition disposition,
- PageTransition::Type transition,
- const std::string& override_encoding);
- virtual void NavigationStateChanged(const TabContents* source,
- unsigned changed_flags);
- virtual void ReplaceContents(TabContents* source,
- TabContents* new_contents);
- 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 LoadingStateChanged(TabContents* source);
- virtual void CloseContents(TabContents* source);
- virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
- virtual bool IsPopup(TabContents* source);
- 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:
- virtual void WillProcessMessage(const MSG& msg);
- virtual void DidProcessMessage(const MSG& msg);
-
- // Initialize the offset used to calculate the position to create windows
- // in |GetWindowCreatePoint|.
- void InitWindowCreatePoint();
-
- // Returns the point where a detached window should be created given the
- // current mouse position.
- gfx::Point GetWindowCreatePoint() const;
-
- // Replaces the TabContents being dragged with the specified |new_contents|.
- // This can occur if the active TabContents for the tab being dragged is
- // replaced, e.g. if a transition from one TabContentsType to another occurs
- // during the drag.
- void ChangeDraggedContents(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 moving the Tab within a TabStrip as well as updating the View.
- void MoveTab(const gfx::Point& screen_point);
-
- // Returns the compatible TabStrip that is under the specified point (screen
- // coordinates), or NULL if there is none.
- TabStrip* GetTabStripForPoint(const gfx::Point& screen_point) const;
-
- // Returns the specified |tabstrip| if it contains the specified point
- // (screen coordinates), NULL if it does not.
- TabStrip* GetTabStripIfItContains(TabStrip* tabstrip,
- const gfx::Point& screen_point) const;
-
- // Attach the dragged Tab to the specified TabStrip.
- void Attach(TabStrip* 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.
- int GetInsertionIndexForDraggedBounds(const gfx::Rect& dragged_bounds) 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 GetDraggedViewPoint(const gfx::Point& screen_point);
-
- // Finds the Tab within the specified TabStrip that corresponds to the
- // dragged TabContents.
- Tab* GetTabMatchingDraggedContents(TabStrip* tabstrip) const;
-
- // Does the work for EndDrag.
- void EndDragImpl(EndDragType how_end);
-
- // If the drag was aborted for some reason, this function is called to un-do
- // the changes made during the drag operation.
- void RevertDrag();
-
- // Finishes the drag operation. Returns true if the drag controller should
- // be destroyed immediately, false otherwise.
- bool CompleteDrag();
-
- // Create the DraggedTabView, if it does not yet exist.
- void EnsureDraggedView();
-
- // 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(ChromeViews::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();
-
- // Cleans up a source tab that is no longer used.
- void CleanUpSourceTab();
-
- // Completes the drag session after the view has animated to its final
- // position.
- void OnAnimateToBoundsComplete();
-
- // The TabContents being dragged. This can get replaced during the drag if
- // the associated NavigationController is navigated to a different
- // TabContentsType.
- 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 Tab that initiated the drag session.
- Tab* source_tab_;
-
- // The TabStrip |source_tab_| originated from.
- TabStrip* 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.
- TabStrip* attached_tabstrip_;
-
- // 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<HWNDPhotobooth> 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_;
-
- // 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_;
-
- // 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.
- ChromeViews::View* old_focused_view_;
-
- bool in_destructor_;
-
- // The horizontal position of the mouse cursor in screen coordinates at the
- // time of the last re-order event.
- int last_move_screen_x_;
-
- DISALLOW_COPY_AND_ASSIGN(DraggedTabController);
-};
-
-#endif // CHROME_BROWSER_TABS_DRAGGED_TAB_CONTROLLER_H_
-
diff --git a/chrome/browser/tabs/dragged_tab_view.cc b/chrome/browser/tabs/dragged_tab_view.cc
deleted file mode 100644
index 0878476..0000000
--- a/chrome/browser/tabs/dragged_tab_view.cc
+++ /dev/null
@@ -1,244 +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/tabs/dragged_tab_view.h"
-
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/browser/tab_contents.h"
-#include "chrome/browser/tabs/hwnd_photobooth.h"
-#include "chrome/browser/tabs/tab_renderer.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/views/hwnd_view_container.h"
-#include "skia/include/SkShader.h"
-
-const int kTransparentAlpha = 200;
-const int kOpaqueAlpha = 255;
-const int kDragFrameBorderSize = 2;
-const int kTwiceDragFrameBorderSize = 2 * kDragFrameBorderSize;
-const float kScalingFactor = 0.5;
-const int kAnimateToBoundsDurationMs = 150;
-static const SkColor kDraggedTabBorderColor = SkColorSetRGB(103, 129, 162);
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabView, public:
-
-DraggedTabView::DraggedTabView(TabContents* datasource,
- const gfx::Point& mouse_tab_offset,
- const gfx::Size& contents_size)
- : container_(NULL),
- renderer_(new TabRenderer),
- attached_(false),
- mouse_tab_offset_(mouse_tab_offset),
- attached_tab_size_(TabRenderer::GetMinimumSelectedSize()),
- photobooth_(NULL),
- contents_size_(contents_size),
- close_animation_(this) {
- SetParentOwned(false);
-
- renderer_->UpdateData(datasource);
-
- container_ = new ChromeViews::HWNDViewContainer;
- 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), false);
- container_->SetContentsView(this);
-}
-
-DraggedTabView::~DraggedTabView() {
- if (close_animation_.IsAnimating())
- close_animation_.Stop();
- GetParent()->RemoveChildView(this);
- container_->Close();
-}
-
-void DraggedTabView::MoveTo(const gfx::Point& screen_point) {
- if (!container_->IsVisible())
- container_->ShowWindow(SW_SHOWNOACTIVATE);
-
- int x;
- if (UILayoutIsRightToLeft() && !attached_) {
- // 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.
- CSize ps;
- GetPreferredSize(&ps);
- x = screen_point.x() - ScaleValue(ps.cx) + 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());
-
- container_->SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
-}
-
-void DraggedTabView::Attach(int selected_width) {
- attached_ = true;
- photobooth_ = NULL;
- attached_tab_size_.set_width(selected_width);
- container_->SetLayeredAlpha(kOpaqueAlpha);
- ResizeContainer();
- Update();
-}
-
-void DraggedTabView::Detach(HWNDPhotobooth* photobooth) {
- attached_ = false;
- photobooth_ = photobooth;
- container_->SetLayeredAlpha(kTransparentAlpha);
- ResizeContainer();
- Update();
-}
-
-void DraggedTabView::Update() {
- container_->set_can_update_layered_window(true);
- SchedulePaint();
- container_->PaintNow(CRect());
- container_->set_can_update_layered_window(false);
-}
-
-void DraggedTabView::AnimateToBounds(const gfx::Rect& bounds,
- Callback0::Type* callback) {
- animation_callback_.reset(callback);
-
- RECT wr;
- GetWindowRect(GetViewContainer()->GetHWND(), &wr);
- animation_start_bounds_ = wr;
- animation_end_bounds_ = bounds;
-
- close_animation_.SetSlideDuration(kAnimateToBoundsDurationMs);
- close_animation_.SetTweenType(SlideAnimation::EASE_OUT);
- if (!close_animation_.IsShowing()) {
- close_animation_.Reset();
- close_animation_.Show();
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabView, AnimationDelegate implementation:
-
-void DraggedTabView::AnimationProgressed(const Animation* animation) {
- int delta_x = (animation_end_bounds_.x() - animation_start_bounds_.x());
- int x = animation_start_bounds_.x() +
- static_cast<int>(delta_x * animation->GetCurrentValue());
- int y = animation_end_bounds_.y();
- container_->SetWindowPos(NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
-}
-
-void DraggedTabView::AnimationEnded(const Animation* animation) {
- animation_callback_->Run();
-}
-
-void DraggedTabView::AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DraggedTabView, ChromeViews::View overrides:
-
-void DraggedTabView::Paint(ChromeCanvas* canvas) {
- if (attached_) {
- PaintAttachedTab(canvas);
- } else {
- PaintDetachedView(canvas);
- }
-}
-
-void DraggedTabView::Layout() {
- CSize ps;
- GetPreferredSize(&ps);
- if (attached_) {
- renderer_->SetBounds(CRect(0, 0, ps.cx, ps.cy));
- } else {
- int left = 0;
- if (UILayoutIsRightToLeft())
- left = ps.cx - attached_tab_size_.width();
- renderer_->SetBounds(CRect(left, 0, left + attached_tab_size_.width(),
- attached_tab_size_.height()));
- }
-}
-
-void DraggedTabView::GetPreferredSize(CSize* out) {
- DCHECK(out);
- if (attached_) {
- *out = attached_tab_size_.ToSIZE();
- } else {
- int width = std::max(attached_tab_size_.width(), contents_size_.width()) +
- kTwiceDragFrameBorderSize;
- int height = attached_tab_size_.height() + kDragFrameBorderSize +
- contents_size_.height();
- *out = CSize(width, height);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// DraggedTabView, private:
-
-void DraggedTabView::PaintAttachedTab(ChromeCanvas* canvas) {
- renderer_->ProcessPaint(canvas);
-}
-
-void DraggedTabView::PaintDetachedView(ChromeCanvas* canvas) {
- CSize ps;
- GetPreferredSize(&ps);
- ChromeCanvas scale_canvas(ps.cx, ps.cy, false);
- SkBitmap& bitmap_device = const_cast<SkBitmap&>(
- scale_canvas.getTopPlatformDevice().accessBitmap(true));
- bitmap_device.eraseARGB(0, 0, 0, 0);
-
- scale_canvas.FillRectInt(kDraggedTabBorderColor, 0,
- attached_tab_size_.height() - kDragFrameBorderSize,
- ps.cx, ps.cy - attached_tab_size_.height());
- int image_x = kDragFrameBorderSize;
- int image_y = attached_tab_size_.height();
- int image_w = ps.cx - kTwiceDragFrameBorderSize;
- int image_h =
- ps.cy - kTwiceDragFrameBorderSize - attached_tab_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.cx, ps.cy);
- 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.cx);
- rc.fBottom = SkIntToScalar(ps.cy);
- canvas->drawRect(rc, paint);
-}
-
-void DraggedTabView::ResizeContainer() {
- CSize ps;
- GetPreferredSize(&ps);
- SetWindowPos(container_->GetHWND(), HWND_TOPMOST, 0, 0, ScaleValue(ps.cx),
- ScaleValue(ps.cy), SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
-}
-
-int DraggedTabView::ScaleValue(int value) {
- return attached_ ? value : static_cast<int>(value * kScalingFactor);
-}
-
diff --git a/chrome/browser/tabs/dragged_tab_view.h b/chrome/browser/tabs/dragged_tab_view.h
deleted file mode 100644
index 8419342..0000000
--- a/chrome/browser/tabs/dragged_tab_view.h
+++ /dev/null
@@ -1,119 +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.
-
-#ifndef CHROME_BROWSER_TABS_DRAGGED_TAB_VIEW_H_
-#define CHROME_BROWSER_TABS_DRAGGED_TAB_VIEW_H_
-
-#include "base/gfx/point.h"
-#include "base/gfx/size.h"
-#include "base/task.h"
-#include "chrome/common/slide_animation.h"
-#include "chrome/views/view.h"
-#include "skia/include/SkBitmap.h"
-
-namespace ChromeViews {
-class HWNDViewContainer;
-}
-namespace gfx {
-class Point;
-}
-class HWNDPhotobooth;
-class Tab;
-class TabContents;
-class TabRenderer;
-
-class DraggedTabView : public ChromeViews::View,
- public AnimationDelegate {
- public:
- DraggedTabView(TabContents* datasource,
- const gfx::Point& mouse_tab_offset,
- const gfx::Size& contents_size);
- virtual ~DraggedTabView();
-
- // Moves the DraggedTabView to the appropriate location given the mouse
- // pointer at |screen_point|.
- void MoveTo(const gfx::Point& screen_point);
-
- // Notifies the DraggedTabView that it has become attached to a TabStrip.
- void Attach(int selected_width);
-
- // Notifies the DraggedTabView that it has been detached from a TabStrip.
- void Detach(HWNDPhotobooth* photobooth);
-
- // Notifies the DraggedTabView that it should update itself.
- void Update();
-
- // Animates the DraggedTabView to the specified bounds, then calls back to
- // |callback|.
- void AnimateToBounds(const gfx::Rect& bounds, Callback0::Type* callback);
-
- // Returns the size of the DraggedTabView. Used when attaching to a TabStrip
- // to determine where to place the Tab in the attached TabStrip.
- gfx::Size attached_tab_size() const { return attached_tab_size_; }
-
- private:
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation);
- virtual void AnimationEnded(const Animation* animation);
- virtual void AnimationCanceled(const Animation* animation);
-
- // Overridden from ChromeViews::View:
- virtual void Paint(ChromeCanvas* canvas);
- virtual void Layout();
- virtual void GetPreferredSize(CSize* out);
-
- // Paint the view, when it's attached to a TabStrip.
- void PaintAttachedTab(ChromeCanvas* canvas);
-
- // Paint the view, when it's not attached to any TabStrip.
- void PaintDetachedView(ChromeCanvas* 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.
- ChromeViews::HWNDViewContainer* container_;
-
- // The renderer that paints the Tab shape.
- scoped_ptr<TabRenderer> renderer_;
-
- // True if the view is currently attached to a TabStrip. Controls rendering
- // and sizing modes.
- bool attached_;
-
- // 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 desired width of the TabRenderer when the DraggedTabView is attached
- // to a TabStrip.
- gfx::Size attached_tab_size_;
-
- // A handle to the DIB containing the current screenshot of the TabContents
- // we are dragging.
- HWNDPhotobooth* photobooth_;
-
- // The dimensions of the TabContents being dragged.
- gfx::Size contents_size_;
-
- // The animation used to slide the attached view to its final location.
- SlideAnimation close_animation_;
-
- // A callback notified when the animation is complete.
- scoped_ptr<Callback0::Type> animation_callback_;
-
- // The start and end bounds of the animation sequence.
- gfx::Rect animation_start_bounds_;
- gfx::Rect animation_end_bounds_;
-
- DISALLOW_EVIL_CONSTRUCTORS(DraggedTabView);
-};
-
-#endif // CHROME_BROWSER_TABS_DRAGGED_TAB_VIEW_H_
-
diff --git a/chrome/browser/tabs/hwnd_photobooth.cc b/chrome/browser/tabs/hwnd_photobooth.cc
deleted file mode 100644
index 7ae6c69..0000000
--- a/chrome/browser/tabs/hwnd_photobooth.cc
+++ /dev/null
@@ -1,159 +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 "base/gfx/point.h"
-#include "chrome/browser/tab_contents.h"
-#include "chrome/browser/tabs/hwnd_photobooth.h"
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/views/hwnd_view_container.h"
-#include "skia/include/SkBitmap.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);
-}
-
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// HWNDPhotobooth, public:
-
-HWNDPhotobooth::HWNDPhotobooth(HWND initial_hwnd)
- : capture_window_(NULL),
- current_hwnd_(initial_hwnd) {
- DCHECK(IsWindow(current_hwnd_));
- CreateCaptureWindow(initial_hwnd);
-}
-
-HWNDPhotobooth::~HWNDPhotobooth() {
- // Detach the attached HWND. The creator of the photo-booth is responsible
- // for destroying it.
- ReplaceHWND(NULL);
- capture_window_->Close();
-}
-
-void HWNDPhotobooth::ReplaceHWND(HWND new_hwnd) {
- if (IsWindow(current_hwnd_) &&
- GetParent(current_hwnd_) == capture_window_->GetHWND()) {
- // 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_->GetHWND());
-
- // 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 HWNDPhotobooth::PaintScreenshotIntoCanvas(
- ChromeCanvas* canvas,
- const gfx::Rect& target_bounds) {
- // Our contained window may have been re-parented. Make sure it belongs to
- // us until someone calls ReplaceHWND(NULL).
- if (IsWindow(current_hwnd_) &&
- GetParent(current_hwnd_) != capture_window_->GetHWND()) {
- ReplaceHWND(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->getTopPlatformDevice().makeOpaque(target_bounds.x(),
- target_bounds.y(),
- target_bounds.width(),
- target_bounds.height());
- ReleaseDC(current_hwnd_, source_dc);
- canvas->endPlatformPaint();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// HWNDPhotobooth, private:
-
-void HWNDPhotobooth::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 ChromeViews::HWNDViewContainer;
- 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, false);
- // If the capture window isn't visible, blitting from the TabContents'
- // HWND's DC to the capture bitmap produces blankness.
- capture_window_->ShowWindow(SW_SHOWNOACTIVATE);
- SetLayeredWindowAttributes(
- capture_window_->GetHWND(), RGB(0xFF, 0xFF, 0xFF), 0xFF, LWA_ALPHA);
-
- ReplaceHWND(initial_hwnd);
-}
diff --git a/chrome/browser/tabs/hwnd_photobooth.h b/chrome/browser/tabs/hwnd_photobooth.h
deleted file mode 100644
index 608236b..0000000
--- a/chrome/browser/tabs/hwnd_photobooth.h
+++ /dev/null
@@ -1,62 +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.
-
-#ifndef CHROME_BROWSER_HWND_PHOTOBOOTH_H__
-#define CHROME_BROWSER_HWND_PHOTOBOOTH_H__
-
-#include "base/basictypes.h"
-#include "base/gfx/rect.h"
-
-class ChromeCanvas;
-namespace ChromeViews {
-class HWNDViewContainer;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// 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 HWNDPhotobooth {
- 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 HWNDPhotobooth(HWND initial_hwnd);
-
- // Destroys the photo booth window.
- virtual ~HWNDPhotobooth();
-
- // Replaces the HWND in the photo booth with the specified one. The caller is
- // responsible for destroying this HWND since it will be detached from the
- // capture window before the capture window is destroyed.
- void ReplaceHWND(HWND new_hwnd);
-
- // Paints the current display image of the window into |canvas|, clipped to
- // |target_bounds|.
- void PaintScreenshotIntoCanvas(ChromeCanvas* 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.
- ChromeViews::HWNDViewContainer* capture_window_;
-
- // The current HWND being captured.
- HWND current_hwnd_;
-
- DISALLOW_EVIL_CONSTRUCTORS(HWNDPhotobooth);
-};
-
-#endif // #ifndef CHROME_BROWSER_HWND_PHOTOBOOTH_H__
-
diff --git a/chrome/browser/tabs/tab.cc b/chrome/browser/tabs/tab.cc
deleted file mode 100644
index f855701..0000000
--- a/chrome/browser/tabs/tab.cc
+++ /dev/null
@@ -1,241 +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/tabs/tab.h"
-
-#include "base/gfx/size.h"
-#include "chrome/views/view_container.h"
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/common/gfx/path.h"
-#include "chrome/common/resource_bundle.h"
-#include "chrome/views/chrome_menu.h"
-#include "chrome/views/tooltip_manager.h"
-#include "generated_resources.h"
-
-const std::string Tab::kTabClassName = "browser/tabs/Tab";
-
-static const SkScalar kTabCapWidth = 15;
-static const SkScalar kTabTopCurveWidth = 4;
-static const SkScalar kTabBottomCurveWidth = 3;
-
-class TabContextMenuController : public ChromeViews::MenuDelegate {
- public:
- explicit TabContextMenuController(Tab* tab)
- : tab_(tab),
- last_command_(TabStripModel::CommandFirst) {
- menu_.reset(new ChromeViews::MenuItemView(this));
- menu_->AppendMenuItemWithLabel(TabStripModel::CommandNewTab,
- l10n_util::GetString(IDS_TAB_CXMENU_NEWTAB));
- menu_->AppendSeparator();
- menu_->AppendMenuItemWithLabel(TabStripModel::CommandReload,
- l10n_util::GetString(IDS_TAB_CXMENU_RELOAD));
- menu_->AppendMenuItemWithLabel(
- TabStripModel::CommandDuplicate,
- l10n_util::GetString(IDS_TAB_CXMENU_DUPLICATE));
- menu_->AppendSeparator();
- menu_->AppendMenuItemWithLabel(
- TabStripModel::CommandCloseTab,
- l10n_util::GetString(IDS_TAB_CXMENU_CLOSETAB));
- menu_->AppendMenuItemWithLabel(
- TabStripModel::CommandCloseOtherTabs,
- l10n_util::GetString(IDS_TAB_CXMENU_CLOSEOTHERTABS));
- menu_->AppendMenuItemWithLabel(
- TabStripModel::CommandCloseTabsToRight,
- l10n_util::GetString(IDS_TAB_CXMENU_CLOSETABSTORIGHT));
- menu_->AppendMenuItemWithLabel(
- TabStripModel::CommandCloseTabsOpenedBy,
- l10n_util::GetString(IDS_TAB_CXMENU_CLOSETABSOPENEDBY));
- }
- virtual ~TabContextMenuController() {
- tab_->delegate()->StopAllHighlighting();
- }
-
- void RunMenuAt(int x, int y) {
- menu_->RunMenuAt(tab_->GetViewContainer()->GetHWND(),
- gfx::Rect(x, y, 0, 0), ChromeViews::MenuItemView::TOPLEFT,
- false);
- }
-
- private:
- // ChromeViews::MenuDelegate implementation:
- virtual bool IsCommandEnabled(int id) const {
- // The MenuItemView used to contain the contents of the Context Menu itself
- // has a command id of 0, and it will check to see if it's enabled for
- // some reason during its construction. The TabStripModel can't handle
- // command indices it doesn't know about, so we need to filter this out
- // here.
- if (id == 0)
- return false;
- return tab_->delegate()->IsCommandEnabledForTab(
- static_cast<TabStripModel::ContextMenuCommand>(id),
- tab_);
- }
-
- virtual void ExecuteCommand(int id) {
- tab_->delegate()->ExecuteCommandForTab(
- static_cast<TabStripModel::ContextMenuCommand>(id),
- tab_);
- }
-
- virtual void SelectionChanged(ChromeViews::MenuItemView* menu) {
- TabStripModel::ContextMenuCommand command =
- static_cast<TabStripModel::ContextMenuCommand>(menu->GetCommand());
- tab_->delegate()->StopHighlightTabsForCommand(last_command_, tab_);
- last_command_ = command;
- tab_->delegate()->StartHighlightTabsForCommand(command, tab_);
- }
-
- private:
- // The context menu.
- scoped_ptr<ChromeViews::MenuItemView> menu_;
-
- // The Tab the context menu was brought up for.
- Tab* tab_;
-
- // 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_EVIL_CONSTRUCTORS(TabContextMenuController);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// Tab, public:
-
-Tab::Tab(TabDelegate* delegate)
- : TabRenderer(),
- delegate_(delegate),
- closing_(false) {
- close_button()->SetListener(this, 0);
- close_button()->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE));
- close_button()->SetAnimationDuration(0);
- SetContextMenuController(this);
-}
-
-Tab::~Tab() {
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Tab, TabRenderer overrides:
-
-bool Tab::IsSelected() const {
- return delegate_->IsTabSelected(this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Tab, ChromeViews::View overrides:
-
-bool Tab::HitTest(const CPoint &l) const {
- gfx::Path path;
- MakePathForTab(&path);
- ScopedHRGN rgn(path.CreateHRGN());
- return !!PtInRegion(rgn, l.x, l.y);
-}
-
-bool Tab::OnMousePressed(const ChromeViews::MouseEvent& event) {
- 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)
- delegate_->SelectTab(this);
- delegate_->MaybeStartDrag(this, event);
- }
- return true;
-}
-
-bool Tab::OnMouseDragged(const ChromeViews::MouseEvent& event) {
- delegate_->ContinueDrag(event);
- return true;
-}
-
-void Tab::OnMouseReleased(const ChromeViews::MouseEvent& event,
- bool canceled) {
- // 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.
- delegate_->EndDrag(canceled);
- if (event.IsMiddleMouseButton())
- delegate_->CloseTab(this);
-}
-
-bool Tab::GetTooltipText(int x, int y, std::wstring* tooltip) {
- std::wstring title = GetTitle();
- if (!title.empty()) {
- // Only show the tooltip if the title is truncated.
- ChromeFont font;
- if (font.GetStringWidth(title) > title_bounds().width()) {
- *tooltip = title;
- return true;
- }
- }
- return false;
-}
-
-bool Tab::GetTooltipTextOrigin(int x, int y, CPoint* origin) {
- ChromeFont font;
- origin->x = title_bounds().x() + 10;
- origin->y = -ChromeViews::TooltipManager::GetTooltipHeight() - 4;
- return true;
-}
-
-bool Tab::GetAccessibleRole(VARIANT* role) {
- DCHECK(role);
-
- role->vt = VT_I4;
- role->lVal = ROLE_SYSTEM_PAGETAB;
- return true;
-}
-
-bool Tab::GetAccessibleName(std::wstring* name) {
- *name = GetTitle();
- return !name->empty();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Tab, ChromeViews::ContextMenuController implementation:
-
-void Tab::ShowContextMenu(ChromeViews::View* source, int x, int y,
- bool is_mouse_gesture) {
- TabContextMenuController controller(this);
- controller.RunMenuAt(x, y);
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// ChromeViews::BaseButton::ButtonListener implementation:
-
-void Tab::ButtonPressed(ChromeViews::BaseButton* sender) {
- if (sender == close_button())
- delegate_->CloseTab(this);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// Tab, private:
-
-void Tab::MakePathForTab(gfx::Path* path) const {
- DCHECK(path);
-
- SkScalar h = SkIntToScalar(GetHeight());
- SkScalar w = SkIntToScalar(GetWidth());
-
- 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();
-}
diff --git a/chrome/browser/tabs/tab.h b/chrome/browser/tabs/tab.h
deleted file mode 100644
index 10346ef..0000000
--- a/chrome/browser/tabs/tab.h
+++ /dev/null
@@ -1,125 +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.
-
-#ifndef CHROME_BROWSER_TABS_TAB_H_
-#define CHROME_BROWSER_TABS_TAB_H_
-
-#include "chrome/browser/tabs/tab_renderer.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/views/base_button.h"
-
-namespace gfx {
-class Path;
-class Point;
-}
-class TabContents;
-class Profile;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// Tab
-//
-// A subclass of TabRenderer that represents an individual Tab in a TabStrip.
-//
-///////////////////////////////////////////////////////////////////////////////
-class Tab : public TabRenderer,
- public ChromeViews::ContextMenuController,
- public ChromeViews::BaseButton::ButtonListener {
- public:
- static const std::string kTabClassName;
-
- // An interface implemented by an object that can help this Tab complete
- // various actions. The index parameter is the index of this Tab in the
- // TabRenderer::Model.
- class TabDelegate {
- public:
- // Returns true if the specified Tab is selected.
- virtual bool IsTabSelected(const Tab* tab) const = 0;
-
- // Selects the specified Tab.
- virtual void SelectTab(Tab* tab) = 0;
-
- // Closes the specified Tab.
- virtual void CloseTab(Tab* tab) = 0;
-
- // Returns true if the specified command is enabled for the specified Tab.
- virtual bool IsCommandEnabledForTab(
- TabStripModel::ContextMenuCommand command_id, const Tab* tab) const = 0;
-
- // Executes the specified command for the specified Tab.
- virtual void ExecuteCommandForTab(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) = 0;
-
- // Starts/Stops highlighting the tabs that will be affected by the
- // specified command for the specified Tab.
- virtual void StartHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) = 0;
- virtual void StopHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) = 0;
- virtual void StopAllHighlighting() = 0;
-
- // Potentially starts a drag for the specified Tab.
- virtual void MaybeStartDrag(Tab* tab,
- const ChromeViews::MouseEvent& event) = 0;
-
- // Continues dragging a Tab.
- virtual void ContinueDrag(const ChromeViews::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.
- virtual void EndDrag(bool canceled) = 0;
- };
-
- explicit Tab(TabDelegate* delegate);
- virtual ~Tab();
-
- // Access the delegate.
- TabDelegate* delegate() const { return delegate_; }
-
- // Used to set/check whether this Tab is being animated closed.
- void set_closing(bool closing) { closing_ = closing; }
- bool closing() const { return closing_; }
-
- // TabRenderer overrides:
- virtual bool IsSelected() const;
-
- // ChromeViews::View overrides:
- virtual bool HitTest(const CPoint &l) const;
- private:
- // ChromeViews::View overrides:
- virtual bool OnMousePressed(const ChromeViews::MouseEvent& event);
- virtual bool OnMouseDragged(const ChromeViews::MouseEvent& event);
- virtual void OnMouseReleased(const ChromeViews::MouseEvent& event,
- bool canceled);
- virtual bool GetTooltipText(int x, int y, std::wstring* tooltip);
- virtual bool GetTooltipTextOrigin(int x, int y, CPoint* origin);
- virtual std::string GetClassName() const { return kTabClassName; }
- virtual bool GetAccessibleRole(VARIANT* role);
- virtual bool GetAccessibleName(std::wstring* name);
-
- // ChromeViews::ContextMenuController overrides:
- virtual void ShowContextMenu(ChromeViews::View* source,
- int x,
- int y,
- bool is_mouse_gesture);
-
- // ChromeViews::BaseButton::ButtonListener overrides:
- virtual void ButtonPressed(ChromeViews::BaseButton* sender);
-
- // Creates a path that contains the clickable region of the tab's visual
- // representation. Used by GetViewForPoint for hit-testing.
- void MakePathForTab(gfx::Path* path) const;
-
- // An instance of a delegate object that can perform various actions based on
- // user gestures.
- TabDelegate* delegate_;
-
- // True if the tab is being animated closed.
- bool closing_;
-
- DISALLOW_COPY_AND_ASSIGN(Tab);
-};
-
-#endif // CHROME_BROWSER_TABS_TAB_H_
-
diff --git a/chrome/browser/tabs/tab_dragging_test.cc b/chrome/browser/tabs/tab_dragging_test.cc
deleted file mode 100644
index 631a0f0..0000000
--- a/chrome/browser/tabs/tab_dragging_test.cc
+++ /dev/null
@@ -1,507 +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 "base/command_line.h"
-#include "base/file_util.h"
-#include "base/time.h"
-#include "chrome/app/chrome_dll_resource.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 "chrome/views/event.h"
-#include "googleurl/src/gurl.h"
-#include "net/base/net_util.h"
-
-
-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, Tab1Tab2) {
- scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
- scoped_ptr<WindowProxy> window(
- automation()->GetWindowForBrowser(browser.get()));
- 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_ptr<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_ptr<TabProxy> tab2(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
-
- // Add Tab_3.
- GURL tab3_url("about:plugins");
- ASSERT_TRUE(browser->AppendTab(tab3_url));
- scoped_ptr<TabProxy> tab3(browser->GetTab(2));
- ASSERT_TRUE(tab3.get());
-
- // Make sure 3 tabs are open
- int final_tab_count = 0;
- ASSERT_TRUE(browser->WaitForTabCountToChange(initial_tab_count,
- &final_tab_count,
- 10000));
- ASSERT_TRUE(final_tab_count == 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 |
- // ---- ---- ----
-
- POINT start;
- POINT end;
- start.x = bounds1.x() + bounds1.width()/2;
- start.y = bounds1.y() + bounds1.height()/2;
- end.x = start.x + 2*bounds1.width()/3;
- end.y = start.y;
- ASSERT_TRUE(browser->SimulateDrag(start, end,
- ChromeViews::Event::EF_LEFT_BUTTON_DOWN,
- false));
-
- // Now check for expected results.
- tab1.reset(browser->GetTab(0));
- ASSERT_TRUE(tab1.get());
- GURL tab1_new_url;
- ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
-
- tab2.reset(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, Tab1Tab3) {
- scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
- scoped_ptr<WindowProxy> window(
- automation()->GetWindowForBrowser(browser.get()));
- 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_ptr<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_ptr<TabProxy> tab2(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
-
- // Add Tab_3.
- GURL tab3_url("about:plugins");
- ASSERT_TRUE(browser->AppendTab(tab3_url));
- scoped_ptr<TabProxy> tab3(browser->GetTab(2));
- ASSERT_TRUE(tab3.get());
-
- // Make sure 3 tabs are open
- int final_tab_count = 0;
- ASSERT_TRUE(browser->WaitForTabCountToChange(initial_tab_count,
- &final_tab_count,
- 10000));
- ASSERT_TRUE(final_tab_count == 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 |
- // ---- ---- ----
-
- POINT start;
- POINT end;
- start.x = bounds1.x() + bounds1.width()/2;
- start.y = bounds1.y() + bounds1.height()/2;
- end.x = start.x + bounds1.width()/2 + bounds2.width() + bounds3.width()/2;
- end.y = start.y;
- ASSERT_TRUE(browser->SimulateDrag(start, end,
- ChromeViews::Event::EF_LEFT_BUTTON_DOWN,
- false));
-
- // Now check for expected results.
- tab1.reset(browser->GetTab(0));
- ASSERT_TRUE(tab1.get());
- GURL tab1_new_url;
- ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
-
- tab2.reset(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
- GURL tab2_new_url;
- ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
-
- tab3.reset(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, Tab1Tab3Escape) {
- scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
- scoped_ptr<WindowProxy> window(
- automation()->GetWindowForBrowser(browser.get()));
- 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_ptr<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_ptr<TabProxy> tab2(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
-
- // Add Tab_3.
- GURL tab3_url("about:plugins");
- ASSERT_TRUE(browser->AppendTab(tab3_url));
- scoped_ptr<TabProxy> tab3(browser->GetTab(2));
- ASSERT_TRUE(tab3.get());
-
- // Make sure 3 tabs are open
- int final_tab_count = 0;
- ASSERT_TRUE(browser->WaitForTabCountToChange(initial_tab_count,
- &final_tab_count,
- 10000));
- ASSERT_TRUE(final_tab_count == 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 |
- // ---- ---- ----
-
- POINT start;
- POINT end;
- start.x = bounds1.x() + bounds1.width()/2;
- start.y = bounds1.y() + bounds1.height()/2;
- end.x = start.x + bounds1.width()/2 + bounds2.width() + bounds3.width()/2;
- end.y = start.y;
-
- // Simulate drag with 'true' as the last parameter. This will interrupt
- // in-flight with Escape.
- ASSERT_TRUE(browser->SimulateDrag(start, end,
- ChromeViews::Event::EF_LEFT_BUTTON_DOWN,
- true));
-
- // Now check for expected results.
- tab1.reset(browser->GetTab(0));
- ASSERT_TRUE(tab1.get());
- GURL tab1_new_url;
- ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
-
- tab2.reset(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
- GURL tab2_new_url;
- ASSERT_TRUE(tab2->GetCurrentURL(&tab2_new_url));
-
- tab3.reset(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, Tab2OutOfTabStrip) {
- scoped_ptr<BrowserProxy> browser(automation()->GetBrowserWindow(0));
- ASSERT_TRUE(browser.get());
- scoped_ptr<WindowProxy> window(
- automation()->GetWindowForBrowser(browser.get()));
- 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_ptr<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_ptr<TabProxy> tab2(browser->GetTab(1));
- ASSERT_TRUE(tab2.get());
-
- // Add Tab_3.
- GURL tab3_url("about:plugins");
- ASSERT_TRUE(browser->AppendTab(tab3_url));
- scoped_ptr<TabProxy> tab3(browser->GetTab(2));
- ASSERT_TRUE(tab3.get());
-
- // Make sure 3 tabs are opened.
- int final_tab_count = 0;
- ASSERT_TRUE(browser->WaitForTabCountToChange(initial_tab_count,
- &final_tab_count,
- 10000));
- ASSERT_TRUE(final_tab_count == 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)
- // ---- ---- ---- ---- ---- ---- ----
-
- POINT start;
- POINT end;
- start.x = bounds2.x() + bounds2.width()/2;
- start.y = bounds2.y() + bounds2.height()/2;
- end.x = start.x;
- end.y = start.y + 3*urlbar_bounds.height();
-
- // Simulate tab drag.
- ASSERT_TRUE(browser->SimulateDrag(start, end,
- ChromeViews::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.reset(browser->GetTab(0));
- ASSERT_TRUE(tab1.get());
- GURL tab1_new_url;
- ASSERT_TRUE(tab1->GetCurrentURL(&tab1_new_url));
-
- tab2.reset(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_ptr<BrowserProxy> browser2(automation()->GetBrowserWindow(1));
- ASSERT_TRUE(browser2.get());
- scoped_ptr<WindowProxy> window2(
- automation()->GetWindowForBrowser(browser2.get()));
- 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_ptr<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/tabs/tab_renderer.cc b/chrome/browser/tabs/tab_renderer.cc
deleted file mode 100644
index 3437900..0000000
--- a/chrome/browser/tabs/tab_renderer.cc
+++ /dev/null
@@ -1,691 +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 <limits>
-
-#include "chrome/browser/tabs/tab_renderer.h"
-
-#include "base/gfx/image_operations.h"
-#include "chrome/app/theme/theme_resources.h"
-#include "chrome/browser/browser.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/tab_contents.h"
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/common/gfx/chrome_font.h"
-#include "chrome/common/resource_bundle.h"
-#include "chrome/common/win_util.h"
-#include "generated_resources.h"
-
-static const int kLeftPadding = 16;
-static const int kTopPadding = 6;
-static const int kRightPadding = 15;
-static const int kBottomPadding = 5;
-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;
-static const int kFaviconSize = 16;
-static const int kSelectedTitleColor = SK_ColorBLACK;
-static const int kUnselectedTitleColor = SkColorSetRGB(64, 64, 64);
-
-// How long the hover state takes.
-static const int kHoverDurationMs = 90;
-
-// How long the pulse throb takes.
-static const int kPulseDurationMs = 200;
-
-// How opaque to make the hover state (out of 1).
-static const double kHoverOpacity = 0.33;
-static const double kHoverOpacityVista = 0.7;
-
-// TODO(beng): (Cleanup) This stuff should move onto the class.
-static ChromeFont title_font;
-static int title_font_height = 0;
-static SkBitmap* close_button_n = NULL;
-static SkBitmap* close_button_h = NULL;
-static SkBitmap* close_button_p = NULL;
-static int close_button_height = 0;
-static int close_button_width = 0;
-static SkBitmap* tab_active_l = NULL;
-static SkBitmap* tab_active_c = NULL;
-static SkBitmap* tab_active_r = NULL;
-static int tab_active_l_width = 0;
-static int tab_active_r_width = 0;
-static SkBitmap* tab_inactive_l = NULL;
-static SkBitmap* tab_inactive_c = NULL;
-static SkBitmap* tab_inactive_r = NULL;
-static SkBitmap* tab_inactive_otr_l = NULL;
-static SkBitmap* tab_inactive_otr_c = NULL;
-static SkBitmap* tab_inactive_otr_r = NULL;
-static SkBitmap* tab_hover_l = NULL;
-static SkBitmap* tab_hover_c = NULL;
-static SkBitmap* tab_hover_r = NULL;
-static int tab_inactive_l_width = 0;
-static int tab_inactive_r_width = 0;
-static SkBitmap* waiting_animation_frames = NULL;
-static SkBitmap* loading_animation_frames = NULL;
-static SkBitmap* crashed_fav_icon = NULL;
-static int loading_animation_frame_count = 0;
-static int waiting_animation_frame_count = 0;
-static int waiting_to_loading_frame_count_ratio = 0;
-static SkBitmap* download_icon = NULL;
-static int download_icon_width = 0;
-static int download_icon_height = 0;
-
-namespace {
-
-void InitResources() {
- static bool initialized = false;
- if (!initialized) {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- title_font = rb.GetFont(ResourceBundle::BaseFont);
- title_font_height = title_font.height();
-
- close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE);
- close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H);
- close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P);
- close_button_width = close_button_n->width();
- close_button_height = close_button_n->height();
-
- tab_active_l = rb.GetBitmapNamed(IDR_TAB_ACTIVE_LEFT);
- tab_active_c = rb.GetBitmapNamed(IDR_TAB_ACTIVE_CENTER);
- tab_active_r = rb.GetBitmapNamed(IDR_TAB_ACTIVE_RIGHT);
- tab_active_l_width = tab_active_l->width();
- tab_active_r_width = tab_active_r->width();
-
- if (win_util::ShouldUseVistaFrame()) {
- tab_inactive_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_V);
- tab_inactive_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_V);
- tab_inactive_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_V);
-
- // Our Vista frame doesn't change background color to show OTR,
- // so we continue to use the existing background tabs.
- tab_inactive_otr_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_V);
- tab_inactive_otr_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_V);
- tab_inactive_otr_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_V);
- } else {
- tab_inactive_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT);
- tab_inactive_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER);
- tab_inactive_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT);
-
- tab_inactive_otr_l = rb.GetBitmapNamed(IDR_TAB_INACTIVE_LEFT_OTR);
- tab_inactive_otr_c = rb.GetBitmapNamed(IDR_TAB_INACTIVE_CENTER_OTR);
- tab_inactive_otr_r = rb.GetBitmapNamed(IDR_TAB_INACTIVE_RIGHT_OTR);
- }
-
- tab_hover_l = rb.GetBitmapNamed(IDR_TAB_HOVER_LEFT);
- tab_hover_c = rb.GetBitmapNamed(IDR_TAB_HOVER_CENTER);
- tab_hover_r = rb.GetBitmapNamed(IDR_TAB_HOVER_RIGHT);
-
- tab_inactive_l_width = tab_inactive_l->width();
- tab_inactive_r_width = tab_inactive_r->width();
-
- // The loading animation image is a strip of states. Each state must be
- // square, so the height must divide the width evenly.
- loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER);
- DCHECK(loading_animation_frames);
- DCHECK(loading_animation_frames->width() %
- loading_animation_frames->height() == 0);
- loading_animation_frame_count =
- loading_animation_frames->width() / loading_animation_frames->height();
-
- waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING);
- DCHECK(waiting_animation_frames);
- DCHECK(waiting_animation_frames->width() %
- waiting_animation_frames->height() == 0);
- waiting_animation_frame_count =
- waiting_animation_frames->width() / waiting_animation_frames->height();
-
- waiting_to_loading_frame_count_ratio =
- waiting_animation_frame_count / loading_animation_frame_count;
-
- crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON);
-
- download_icon = rb.GetBitmapNamed(IDR_DOWNLOAD_ICON);
- download_icon_width = download_icon->width();
- download_icon_height = download_icon->height();
-
- initialized = true;
- }
-}
-
-int GetContentHeight() {
- // 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, title_font_height);
- return std::max(content_height, close_button_height);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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 ChromeViews::Button {
- public:
- TabCloseButton() : Button() {}
- virtual ~TabCloseButton() {}
-
- virtual bool OnMousePressed(const ChromeViews::MouseEvent& event) {
- return !event.IsOnlyMiddleMouseButton();
- }
-
- // 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 ChromeViews::MouseEvent& event) {
- BaseButton::OnMouseEntered(event);
- GetParent()->OnMouseEntered(event);
- }
-
- virtual void OnMouseExited(const ChromeViews::MouseEvent& event) {
- BaseButton::OnMouseExited(event);
- GetParent()->OnMouseExited(event);
- }
-
- private:
- DISALLOW_EVIL_CONSTRUCTORS(TabCloseButton);
-};
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// FaviconCrashAnimation
-//
-// A custom animation subclass to manage the favicon crash animation.
-class TabRenderer::FavIconCrashAnimation : public Animation,
- public AnimationDelegate {
- public:
- explicit FavIconCrashAnimation(TabRenderer* target)
- : Animation(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:
- TabRenderer* target_;
-
- DISALLOW_EVIL_CONSTRUCTORS(FavIconCrashAnimation);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, public:
-
-TabRenderer::TabRenderer()
- : animation_state_(ANIMATION_NONE),
- animation_frame_(0),
- showing_icon_(false),
- showing_download_icon_(false),
- showing_close_button_(false),
- crash_animation_(NULL),
- fav_icon_hiding_offset_(0),
- should_display_crashed_favicon_(false) {
- InitResources();
-
- // Add the Close Button.
- close_button_ = new TabCloseButton;
- close_button_->SetImage(ChromeViews::Button::BS_NORMAL, close_button_n);
- close_button_->SetImage(ChromeViews::Button::BS_HOT, close_button_h);
- close_button_->SetImage(ChromeViews::Button::BS_PUSHED, close_button_p);
- AddChildView(close_button_);
-
- hover_animation_.reset(new SlideAnimation(this));
- hover_animation_->SetSlideDuration(kHoverDurationMs);
-
- pulse_animation_.reset(new ThrobAnimation(this));
- pulse_animation_->SetSlideDuration(kPulseDurationMs);
-}
-
-TabRenderer::~TabRenderer() {
- delete crash_animation_;
-}
-
-void TabRenderer::UpdateData(TabContents* contents) {
- DCHECK(contents);
- data_.favicon = contents->GetFavIcon();
- data_.title = contents->GetTitle();
- data_.loading = contents->is_loading();
- data_.off_the_record = contents->profile()->IsOffTheRecord();
- data_.show_icon = contents->ShouldDisplayFavIcon();
- data_.show_download_icon = contents->IsDownloadShelfVisible();
- data_.crashed = contents->IsCrashed();
-}
-
-void TabRenderer::UpdateFromModel() {
- // Force a layout, since the tab may have grown a favicon.
- Layout();
- SchedulePaint();
-
- if (data_.crashed) {
- if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation())
- StartCrashAnimation();
- } else {
- if (IsPerformingCrashAnimation())
- StopCrashAnimation();
- ResetCrashedFavIcon();
- }
-}
-
-bool TabRenderer::IsSelected() const {
- return true;
-}
-
-void TabRenderer::ValidateLoadingAnimation(AnimationState animation_state) {
- if (animation_state_ != animation_state) {
- // 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 (animation_state_ == ANIMATION_WAITING &&
- animation_state == ANIMATION_LOADING) {
- animation_frame_ = loading_animation_frame_count -
- (animation_frame_ / waiting_to_loading_frame_count_ratio);
- }
- animation_state_ = animation_state;
- }
-
- if (animation_state_ != ANIMATION_NONE) {
- animation_frame_ = ++animation_frame_ %
- ((animation_state_ == ANIMATION_WAITING) ?
- waiting_animation_frame_count :
- loading_animation_frame_count);
- } else {
- animation_frame_ = 0;
- }
-
- SchedulePaint();
-}
-
-void TabRenderer::StartPulse() {
- pulse_animation_->Reset();
- pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
-}
-
-void TabRenderer::StopPulse() {
- if (pulse_animation_->IsAnimating())
- pulse_animation_->Stop();
-}
-
-// static
-gfx::Size TabRenderer::GetMinimumSize() {
- InitResources();
-
- 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_l->height());
- return minimum_size;
-}
-
-// static
-gfx::Size TabRenderer::GetMinimumSelectedSize() {
- gfx::Size minimum_size = GetMinimumSize();
- minimum_size.set_width(kLeftPadding + kFaviconSize + kRightPadding);
- return minimum_size;
-}
-
-// static
-gfx::Size TabRenderer::GetStandardSize() {
- gfx::Size standard_size = GetMinimumSize();
- standard_size.set_width(
- standard_size.width() + kFavIconTitleSpacing + kStandardTitleWidth);
- return standard_size;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, protected:
-
-std::wstring TabRenderer::GetTitle() const {
- return data_.title;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, ChromeViews::View overrides:
-
-void TabRenderer::Paint(ChromeCanvas* canvas) {
- // Don't paint if we're narrower than we can render correctly. (This should
- // only happen during animations).
- if (GetWidth() < GetMinimumSize().width())
- return;
-
- // See if the model changes whether the icons should be painted.
- const bool show_icon = ShouldShowIcon();
- const bool show_download_icon = data_.show_download_icon;
- const bool show_close_button = ShouldShowCloseBox();
- if (show_icon != showing_icon_ ||
- show_download_icon != showing_download_icon_ ||
- show_close_button != showing_close_button_)
- Layout();
-
- PaintTabBackground(canvas);
-
- // Paint the loading animation if the page is currently loading, otherwise
- // show the page's favicon.
- if (show_icon) {
- if (animation_state_ != ANIMATION_NONE) {
- PaintLoadingAnimation(canvas);
- } else {
- canvas->save();
- canvas->ClipRectInt(0, 0, GetWidth(), GetHeight() - 4);
- if (should_display_crashed_favicon_) {
- canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0,
- crashed_fav_icon->width(),
- crashed_fav_icon->height(),
- favicon_bounds_.x(),
- favicon_bounds_.y() + fav_icon_hiding_offset_,
- kFaviconSize, kFaviconSize,
- true);
- } else {
- if (!data_.favicon.isNull()) {
- canvas->DrawBitmapInt(data_.favicon, 0, 0,
- data_.favicon.width(),
- data_.favicon.height(),
- favicon_bounds_.x(),
- favicon_bounds_.y() + fav_icon_hiding_offset_,
- kFaviconSize, kFaviconSize,
- true);
- }
- }
- canvas->restore();
- }
- }
-
- if (show_download_icon) {
- canvas->DrawBitmapInt(*download_icon,
- download_icon_bounds_.x(), download_icon_bounds_.y());
- }
-
- // Paint the Title.
- std::wstring title = data_.title;
- if (title.empty()) {
- if (data_.loading) {
- title = l10n_util::GetString(IDS_TAB_LOADING_TITLE);
- } else {
- title = l10n_util::GetString(IDS_TAB_UNTITLED_TITLE);
- }
- } else {
- Browser::FormatTitleForDisplay(&title);
- }
-
- SkColor title_color = IsSelected() ? kSelectedTitleColor
- : kUnselectedTitleColor;
- canvas->DrawStringInt(title, title_font, title_color, title_bounds_.x(),
- title_bounds_.y(), title_bounds_.width(),
- title_bounds_.height());
-}
-
-void TabRenderer::Layout() {
- CRect lb;
- GetLocalBounds(&lb, false);
- if (lb.IsRectEmpty())
- return;
-
- lb.left += kLeftPadding;
- lb.top += kTopPadding;
- lb.bottom -= kBottomPadding;
- lb.right -= kRightPadding;
-
- // First of all, figure out who is tallest.
- int content_height = GetContentHeight();
-
- // Size the Favicon.
- showing_icon_ = ShouldShowIcon();
- if (showing_icon_) {
- int favicon_top = kTopPadding + (content_height - kFaviconSize) / 2;
- favicon_bounds_.SetRect(lb.left, favicon_top, kFaviconSize, kFaviconSize);
- } else {
- favicon_bounds_.SetRect(lb.left, lb.top, 0, 0);
- }
-
- // Size the download icon.
- showing_download_icon_ = data_.show_download_icon;
- if (showing_download_icon_) {
- int icon_top = kTopPadding + (content_height - download_icon_height) / 2;
- download_icon_bounds_.SetRect(lb.Width() - download_icon_width, icon_top,
- download_icon_width, download_icon_height);
- }
-
- // Size the Close button.
- showing_close_button_ = ShouldShowCloseBox();
- if (showing_close_button_) {
- int close_button_top =
- kTopPadding + kCloseButtonVertFuzz +
- (content_height - close_button_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_width,
- close_button_height);
- close_button_->SetVisible(true);
- } else {
- close_button_->SetBounds(0, 0, 0, 0);
- close_button_->SetVisible(false);
- }
-
- // Size the Title text to fill the remaining space.
- int title_left = favicon_bounds_.right() + kFavIconTitleSpacing;
- int title_top = kTopPadding + (content_height - title_font_height) / 2;
-
- // 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 = GetMinimumSize();
- int text_height = title_top + title_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_->GetX() -
- kTitleCloseButtonSpacing - title_left, 0);
- } else {
- title_width = std::max(lb.Width() - title_left, 0);
- }
- if (data_.show_download_icon)
- title_width = std::max(title_width - download_icon_width, 0);
- title_bounds_.SetRect(title_left, title_top, title_width, title_font_height);
-
- // Certain UI elements within the Tab (the favicon, the download icon, 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 ChromeViews::Button instance) are automatically mirrored by the
- // mirroring infrastructure in ChromeViews. The elements Tab draws directly
- // on the canvas need to be manually mirrored if the View's layout is
- // right-to-left.
- favicon_bounds_.set_x(MirroredLeftPointForRect(favicon_bounds_));
- title_bounds_.set_x(MirroredLeftPointForRect(title_bounds_));
- download_icon_bounds_.set_x(MirroredLeftPointForRect(download_icon_bounds_));
-}
-
-void TabRenderer::DidChangeBounds(const CRect& previous,
- const CRect& current) {
- Layout();
-}
-
-
-void TabRenderer::OnMouseEntered(const ChromeViews::MouseEvent& e) {
- hover_animation_->SetTweenType(SlideAnimation::EASE_OUT);
- hover_animation_->Show();
-}
-
-void TabRenderer::OnMouseExited(const ChromeViews::MouseEvent& e) {
- hover_animation_->SetTweenType(SlideAnimation::EASE_IN);
- hover_animation_->Hide();
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabRenderer, AnimationDelegate implementation:
-
-void TabRenderer::AnimationProgressed(const Animation* animation) {
- SchedulePaint();
-}
-
-void TabRenderer::AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
-}
-
-void TabRenderer::AnimationEnded(const Animation* animation) {
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, private
-
-void TabRenderer::PaintTabBackground(ChromeCanvas* canvas) {
- if (IsSelected()) {
- // Sometimes detaching a tab quickly can result in the model reporting it
- // as not being selected, so is_drag_clone_ ensures that we always paint
- // the active representation for the dragged tab.
- PaintActiveTabBackground(canvas);
- } else {
- // Draw our hover state.
- Animation* animation = hover_animation_.get();
- if (pulse_animation_->IsAnimating())
- animation = pulse_animation_.get();
- if (animation->GetCurrentValue() > 0) {
- PaintHoverTabBackground(canvas, animation->GetCurrentValue() *
- (win_util::ShouldUseVistaFrame() ?
- kHoverOpacityVista : kHoverOpacity));
- } else {
- PaintInactiveTabBackground(canvas);
- }
- }
-}
-
-void TabRenderer::PaintInactiveTabBackground(ChromeCanvas* canvas) {
- bool is_otr = data_.off_the_record;
- canvas->DrawBitmapInt(is_otr ? *tab_inactive_otr_l : *tab_inactive_l, 0, 0);
- canvas->TileImageInt(is_otr ? *tab_inactive_otr_c : *tab_inactive_c,
- tab_inactive_l_width, 0,
- GetWidth() - tab_inactive_l_width - tab_inactive_r_width,
- GetHeight());
- canvas->DrawBitmapInt(is_otr ? *tab_inactive_otr_r : *tab_inactive_r,
- GetWidth() - tab_inactive_r_width, 0);
-}
-
-void TabRenderer::PaintActiveTabBackground(ChromeCanvas* canvas) {
- canvas->DrawBitmapInt(*tab_active_l, 0, 0);
- canvas->TileImageInt(*tab_active_c, tab_active_l_width, 0,
- GetWidth() - tab_active_l_width - tab_active_r_width, GetHeight());
- canvas->DrawBitmapInt(*tab_active_r, GetWidth() - tab_active_r_width, 0);
-}
-
-void TabRenderer::PaintHoverTabBackground(ChromeCanvas* canvas,
- double opacity) {
- bool is_otr = data_.off_the_record;
- SkBitmap left = gfx::ImageOperations::CreateBlendedBitmap(
- (is_otr ? *tab_inactive_otr_l : *tab_inactive_l),
- *tab_hover_l, opacity);
- SkBitmap center = gfx::ImageOperations::CreateBlendedBitmap(
- (is_otr ? *tab_inactive_otr_c : *tab_inactive_c),
- *tab_hover_c, opacity);
- SkBitmap right = gfx::ImageOperations::CreateBlendedBitmap(
- (is_otr ? *tab_inactive_otr_r : *tab_inactive_r),
- *tab_hover_r, opacity);
-
- canvas->DrawBitmapInt(left, 0, 0);
- canvas->TileImageInt(center, tab_active_l_width, 0,
- GetWidth() - tab_active_l_width - tab_active_r_width, GetHeight());
- canvas->DrawBitmapInt(right, GetWidth() - tab_active_r_width, 0);
-}
-
-void TabRenderer::PaintLoadingAnimation(ChromeCanvas* canvas) {
- SkBitmap* frames = (animation_state_ == ANIMATION_WAITING) ?
- waiting_animation_frames : loading_animation_frames;
- int image_size = frames->height();
- int image_offset = animation_frame_ * image_size;
- int dst_y = (GetHeight() - image_size) / 2;
-
- // Just like with the Tab's title and favicon, the position for the page
- // loading animation also needs to be mirrored if the View's UI layout is
- // right-to-left.
- int dst_x;
- if (UILayoutIsRightToLeft()) {
- dst_x = GetWidth() - kLeftPadding - image_size;
- } else {
- dst_x = kLeftPadding;
- }
- canvas->DrawBitmapInt(*frames, image_offset, 0, image_size,
- image_size, dst_x, dst_y, image_size, image_size,
- false);
-}
-
-int TabRenderer::IconCapacity() const {
- if (GetHeight() < GetMinimumSize().height()) {
- return 0;
- }
- return (GetWidth() - kLeftPadding - kRightPadding) / kFaviconSize;
-}
-
-bool TabRenderer::ShouldShowIcon() const {
- 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 TabRenderer::ShouldShowCloseBox() const {
- // The selected tab never clips close button.
- return IsSelected() || IconCapacity() >= 3;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// TabRenderer, private:
-
-void TabRenderer::StartCrashAnimation() {
- if (!crash_animation_)
- crash_animation_ = new FavIconCrashAnimation(this);
- crash_animation_->Reset();
- crash_animation_->Start();
-}
-
-void TabRenderer::StopCrashAnimation() {
- if (!crash_animation_)
- return;
- crash_animation_->Stop();
-}
-
-bool TabRenderer::IsPerformingCrashAnimation() const {
- return crash_animation_ && crash_animation_->IsAnimating();
-}
-
-void TabRenderer::SetFavIconHidingOffset(int offset) {
- fav_icon_hiding_offset_ = offset;
- SchedulePaint();
-}
-
-void TabRenderer::DisplayCrashedFavIcon() {
- should_display_crashed_favicon_ = true;
-}
-
-void TabRenderer::ResetCrashedFavIcon() {
- should_display_crashed_favicon_ = false;
-}
-
diff --git a/chrome/browser/tabs/tab_renderer.h b/chrome/browser/tabs/tab_renderer.h
deleted file mode 100644
index 25c2de8..0000000
--- a/chrome/browser/tabs/tab_renderer.h
+++ /dev/null
@@ -1,174 +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.
-
-#ifndef CHROME_BROWSER_TABS_TAB_RENDERER_H__
-#define CHROME_BROWSER_TABS_TAB_RENDERER_H__
-
-#include "base/gfx/point.h"
-#include "chrome/common/animation.h"
-#include "chrome/common/slide_animation.h"
-#include "chrome/common/throb_animation.h"
-#include "chrome/views/button.h"
-#include "chrome/views/menu.h"
-#include "chrome/views/view.h"
-
-class TabContents;
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// TabRenderer
-//
-// A View that renders a Tab, either in a TabStrip or in a DraggedTabView.
-//
-///////////////////////////////////////////////////////////////////////////////
-class TabRenderer : public ChromeViews::View,
- public AnimationDelegate {
- public:
- // Possible animation states.
- enum AnimationState {
- ANIMATION_NONE,
- ANIMATION_WAITING,
- ANIMATION_LOADING
- };
-
- TabRenderer();
- virtual ~TabRenderer();
-
- // Updates the data the Tab uses to render itself from the specified
- // TabContents.
- void UpdateData(TabContents* contents);
-
- // Updates the display to reflect the contents of this TabRenderer's model.
- void UpdateFromModel();
-
- // Returns true if the Tab is selected, false otherwise.
- virtual bool IsSelected() const;
-
- // Advance the Loading Animation to the next frame, or hide the animation if
- // the tab isn't loading.
- void ValidateLoadingAnimation(AnimationState animation_state);
-
- // Starts/Stops a pulse animation.
- void StartPulse();
- void StopPulse();
-
- // Returns the minimum possible size of a single unselected Tab.
- static gfx::Size GetMinimumSize();
- // 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();
-
- protected:
- ChromeViews::Button* close_button() const { return close_button_; }
- const gfx::Rect& title_bounds() const { return title_bounds_; }
-
- // Returns the title of the Tab.
- std::wstring GetTitle() const;
-
- private:
- // Overridden from ChromeViews::View:
- virtual void Paint(ChromeCanvas* canvas);
- virtual void Layout();
- virtual void DidChangeBounds(const CRect& previous, const CRect& current);
- virtual void OnMouseEntered(const ChromeViews::MouseEvent& event);
- virtual void OnMouseExited(const ChromeViews::MouseEvent& event);
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation);
- virtual void AnimationCanceled(const Animation* animation);
- virtual void AnimationEnded(const Animation* animation);
-
- // Starts/Stops the crash animation.
- void StartCrashAnimation();
- void StopCrashAnimation();
-
- // Return true if the crash animation is currently running.
- bool IsPerformingCrashAnimation() const;
-
- // Set the temporary offset for the favicon. This is used during animation.
- void SetFavIconHidingOffset(int offset);
-
- void DisplayCrashedFavIcon();
- void ResetCrashedFavIcon();
-
- // Paint various portions of the Tab
- void PaintTabBackground(ChromeCanvas* canvas);
- void PaintInactiveTabBackground(ChromeCanvas* canvas);
- void PaintActiveTabBackground(ChromeCanvas* canvas);
- void PaintHoverTabBackground(ChromeCanvas* canvas, double opacity);
- void PaintLoadingAnimation(ChromeCanvas* 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;
-
- // The bounds of various sections of the display.
- gfx::Rect favicon_bounds_;
- gfx::Rect download_icon_bounds_;
- gfx::Rect title_bounds_;
-
- // Current state of the animation.
- AnimationState animation_state_;
-
- // The current index into the Animation image strip.
- int animation_frame_;
-
- // Close Button.
- ChromeViews::Button* close_button_;
-
- // Hover animation.
- scoped_ptr<SlideAnimation> hover_animation_;
-
- // Pulse animation.
- scoped_ptr<ThrobAnimation> pulse_animation_;
-
- // Model data. We store this here so that we don't need to ask the underlying
- // model, which is tricky since instances of this object can outlive the
- // corresponding objects in the underlying model.
- struct TabData {
- SkBitmap favicon;
- std::wstring title;
- bool loading;
- bool crashed;
- bool off_the_record;
- bool show_icon;
- bool show_download_icon;
- };
- TabData data_;
-
- // 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 download icon. Comes from the model.
- bool showing_download_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 offset used to animate the favicon location.
- int fav_icon_hiding_offset_;
-
- // The animation object used to swap the favicon with the sad tab icon.
- class FavIconCrashAnimation;
- FavIconCrashAnimation* crash_animation_;
-
- bool should_display_crashed_favicon_;
-
- DISALLOW_EVIL_CONSTRUCTORS(TabRenderer);
-};
-
-#endif // CHROME_BROWSER_TABS_TAB_RENDERER_H__
-
diff --git a/chrome/browser/tabs/tab_strip.cc b/chrome/browser/tabs/tab_strip.cc
deleted file mode 100644
index 57a8e32..0000000
--- a/chrome/browser/tabs/tab_strip.cc
+++ /dev/null
@@ -1,1524 +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/tabs/tab_strip.h"
-
-#include "base/gfx/size.h"
-#include "chrome/app/theme/theme_resources.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/tab_contents.h"
-#include "chrome/browser/tabs/dragged_tab_controller.h"
-#include "chrome/browser/tabs/tab.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/browser/user_metrics.h"
-#include "chrome/browser/view_ids.h"
-#include "chrome/browser/vista_frame.h"
-#include "chrome/browser/web_contents.h"
-#include "chrome/common/drag_drop_types.h"
-#include "chrome/common/gfx/chrome_canvas.h"
-#include "chrome/common/l10n_util.h"
-#include "chrome/common/os_exchange_data.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/resource_bundle.h"
-#include "chrome/common/slide_animation.h"
-#include "chrome/common/stl_util-inl.h"
-#include "chrome/common/win_util.h"
-#include "chrome/views/image_view.h"
-#include "chrome/views/painter.h"
-
-#include "generated_resources.h"
-
-#undef min
-#undef max
-
-using ChromeViews::DropTargetEvent;
-
-static const int kDefaultAnimationDurationMs = 100;
-static const int kResizeLayoutAnimationDurationMs = 166;
-static const int kReorderAnimationDurationMs = 166;
-
-static const int kLoadingAnimationFrameTimeMs = 30;
-static const int kNewTabButtonHOffset = -5;
-static const int kNewTabButtonVOffset = 5;
-static const int kResizeTabsTimeMs = 300;
-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));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// TabAnimation
-//
-// A base class for all TabStrip animations.
-//
-class TabStrip::TabAnimation : public AnimationDelegate {
- public:
- friend class TabStrip;
-
- // Possible types of animation.
- enum Type {
- INSERT,
- REMOVE,
- MOVE,
- RESIZE
- };
-
- TabAnimation(TabStrip* tabstrip, Type type)
- : tabstrip_(tabstrip),
- animation_(this),
- start_selected_width_(0),
- start_unselected_width_(0),
- end_selected_width_(0),
- end_unselected_width_(0),
- layout_on_completion_(false),
- type_(type) {
- }
- virtual ~TabAnimation() {}
-
- Type type() const { return type_; }
-
- void Start() {
- animation_.SetSlideDuration(GetDuration());
- animation_.SetTweenType(SlideAnimation::EASE_OUT);
- if (!animation_.IsShowing()) {
- animation_.Reset();
- animation_.Show();
- }
- }
-
- void Stop() {
- animation_.Stop();
- }
-
- void set_layout_on_completion(bool layout_on_completion) {
- layout_on_completion_ = layout_on_completion;
- }
-
- // Retrieves the width for the Tab at the specified index if an animation is
- // active.
- static double GetCurrentTabWidth(TabStrip* tabstrip,
- TabStrip::TabAnimation* animation,
- int index) {
- double unselected, selected;
- tabstrip->GetCurrentTabWidths(&unselected, &selected);
- Tab* tab = tabstrip->GetTabAt(index);
- double tab_width = tab->IsSelected() ? selected : unselected;
- if (animation) {
- double specified_tab_width = animation->GetWidthForTab(index);
- if (specified_tab_width != -1)
- tab_width = specified_tab_width;
- }
- return tab_width;
- }
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation) {
- tabstrip_->AnimationLayout(end_unselected_width_);
- }
-
- virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->FinishAnimation(this, layout_on_completion_);
- // This object is destroyed now, so we can't do anything else after this.
- }
-
- virtual void AnimationCanceled(const Animation* animation) {
- AnimationEnded(animation);
- }
-
- protected:
- // Returns the duration of the animation.
- virtual int GetDuration() const {
- return kDefaultAnimationDurationMs;
- }
-
- // Subclasses override to return the width of the Tab at the specified index
- // at the current animation frame. -1 indicates the default width should be
- // used for the Tab.
- virtual double GetWidthForTab(int index) const {
- return -1; // Use default.
- }
-
- // Figure out the desired start and end widths for the specified pre- and
- // post- animation tab counts.
- void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count) {
- tabstrip_->GetDesiredTabWidths(start_tab_count, &start_unselected_width_,
- &start_selected_width_);
- double standard_tab_width =
- static_cast<double>(TabRenderer::GetStandardSize().width());
- if (start_tab_count < end_tab_count &&
- start_unselected_width_ < standard_tab_width) {
- double minimum_tab_width =
- static_cast<double>(TabRenderer::GetMinimumSize().width());
- start_unselected_width_ -= minimum_tab_width / start_tab_count;
- }
- tabstrip_->GenerateIdealBounds();
- tabstrip_->GetDesiredTabWidths(end_tab_count,
- &end_unselected_width_,
- &end_selected_width_);
- }
-
- TabStrip* tabstrip_;
- SlideAnimation animation_;
-
- double start_selected_width_;
- double start_unselected_width_;
- double end_selected_width_;
- double end_unselected_width_;
-
- private:
- // True if a complete re-layout is required upon completion of the animation.
- // Subclasses set this if they don't perform a complete layout
- // themselves and canceling the animation may leave the strip in an
- // inconsistent state.
- bool layout_on_completion_;
-
- const Type type_;
-
- DISALLOW_EVIL_CONSTRUCTORS(TabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles insertion of a Tab at |index|.
-class InsertTabAnimation : public TabStrip::TabAnimation {
- public:
- explicit InsertTabAnimation(TabStrip* tabstrip, int index)
- : TabAnimation(tabstrip, INSERT),
- index_(index) {
- int tab_count = tabstrip->GetTabCount();
- GenerateStartAndEndWidths(tab_count - 1, tab_count);
- }
- virtual ~InsertTabAnimation() {}
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual double GetWidthForTab(int index) const {
- if (index == index_) {
- bool is_selected = tabstrip_->model()->selected_index() == index;
- double target_width =
- is_selected ? end_unselected_width_ : end_selected_width_;
- double start_width = is_selected ? Tab::GetMinimumSelectedSize().width() :
- Tab::GetMinimumSize().width();
- double delta = target_width - start_width;
- if (delta > 0)
- return start_width + (delta * animation_.GetCurrentValue());
- return start_width;
- }
- if (tabstrip_->GetTabAt(index)->IsSelected()) {
- double delta = end_selected_width_ - start_selected_width_;
- return start_selected_width_ + (delta * animation_.GetCurrentValue());
- }
- double delta = end_unselected_width_ - start_unselected_width_;
- return start_unselected_width_ + (delta * animation_.GetCurrentValue());
- }
-
- private:
- int index_;
-
- DISALLOW_EVIL_CONSTRUCTORS(InsertTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles removal of a Tab from |index|
-class RemoveTabAnimation : public TabStrip::TabAnimation {
- public:
- RemoveTabAnimation(TabStrip* tabstrip, int index, TabContents* contents)
- : TabAnimation(tabstrip, REMOVE),
- index_(index) {
- int tab_count = tabstrip->GetTabCount();
- GenerateStartAndEndWidths(tab_count, tab_count - 1);
- }
-
- // Returns the index of the tab being removed.
- int index() const { return index_; }
-
- virtual ~RemoveTabAnimation() {
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual double GetWidthForTab(int index) const {
- Tab* tab = tabstrip_->GetTabAt(index);
- if (index == index_) {
- // The tab(s) being removed are gradually shrunken depending on the state
- // of the animation.
- // Removed animated Tabs are never selected.
- double start_width = start_unselected_width_;
- double target_width = Tab::GetMinimumSize().width() + kTabHOffset;
- double delta = start_width - target_width;
- return start_width - (delta * animation_.GetCurrentValue());
- }
- if (tabstrip_->available_width_for_tabs_ != -1 &&
- index_ != tabstrip_->GetTabCount() - 1) {
- return TabStrip::TabAnimation::GetWidthForTab(index);
- }
- // All other tabs are sized according to the start/end widths specified at
- // the start of the animation.
- if (tab->IsSelected()) {
- double delta = end_selected_width_ - start_selected_width_;
- return start_selected_width_ + (delta * animation_.GetCurrentValue());
- }
- double delta = end_unselected_width_ - start_unselected_width_;
- return start_unselected_width_ + (delta * animation_.GetCurrentValue());
- }
-
- virtual void AnimationEnded(const Animation* animation) {
- RemoveTabAt(index_);
- HighlightCloseButton();
- TabStrip::TabAnimation::AnimationEnded(animation);
- }
-
- private:
- // Cleans up the Tab from the TabStrip at the specified |index| once its
- // animated removal is complete.
- void RemoveTabAt(int index) const {
- // Save a pointer to the Tab before we remove the TabData, we'll need this
- // later.
- Tab* removed = tabstrip_->tab_data_.at(index).tab;
-
- // Remove the Tab from the TabStrip's list...
- tabstrip_->tab_data_.erase(tabstrip_->tab_data_.begin() + index);
-
- // If the TabContents being detached was removed as a result of a drag
- // gesture from its corresponding Tab, we don't want to remove the Tab from
- // the child list, because if we do so it'll stop receiving events and the
- // drag will stall. So we only remove if a drag isn't active, or the Tab
- // was for some other TabContents.
- if (!tabstrip_->IsDragSessionActive() ||
- !tabstrip_->drag_controller_->IsDragSourceTab(removed)) {
- tabstrip_->RemoveChildView(removed);
- delete removed;
- }
- }
-
- // When the animation completes, we send the ViewContainer 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_->available_width_for_tabs_ == -1 ||
- tabstrip_->IsDragSessionActive()) {
- // This function is not required (and indeed may crash!) for removes
- // spawned by non-mouse closes and drag-detaches.
- return;
- }
-
- POINT pt;
- GetCursorPos(&pt);
- ChromeViews::ViewContainer* vc = tabstrip_->GetViewContainer();
- RECT wr;
- GetWindowRect(vc->GetHWND(), &wr);
- pt.x -= wr.left;
- pt.y -= wr.top;
-
- // Return to message loop - otherwise we may disrupt some operation that's
- // in progress.
- PostMessage(vc->GetHWND(), WM_MOUSEMOVE, 0, MAKELPARAM(pt.x, pt.y));
- }
-
- int index_;
-
- DISALLOW_EVIL_CONSTRUCTORS(RemoveTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles the movement of a Tab from one position to another.
-class MoveTabAnimation : public TabStrip::TabAnimation {
- public:
- MoveTabAnimation(TabStrip* tabstrip, int tab_a_index, int tab_b_index)
- : TabAnimation(tabstrip, MOVE),
- start_tab_a_bounds_(tabstrip_->GetIdealBounds(tab_b_index)),
- start_tab_b_bounds_(tabstrip_->GetIdealBounds(tab_a_index)) {
- tab_a_ = tabstrip_->GetTabAt(tab_a_index);
- tab_b_ = tabstrip_->GetTabAt(tab_b_index);
-
- // Since we don't do a full TabStrip re-layout, we need to force a full
- // layout upon completion since we're not guaranteed to be in a good state
- // if for example the animation is canceled.
- set_layout_on_completion(true);
- }
- virtual ~MoveTabAnimation() {}
-
- // Overridden from AnimationDelegate:
- virtual void AnimationProgressed(const Animation* animation) {
- // Position Tab A
- double distance = start_tab_b_bounds_.x() - start_tab_a_bounds_.x();
- double delta = distance * animation_.GetCurrentValue();
- double new_x = start_tab_a_bounds_.x() + delta;
- tab_a_->SetBounds(Round(new_x), tab_a_->GetY(), tab_a_->GetWidth(),
- tab_a_->GetHeight());
-
- // Position Tab B
- distance = start_tab_a_bounds_.x() - start_tab_b_bounds_.x();
- delta = distance * animation_.GetCurrentValue();
- new_x = start_tab_b_bounds_.x() + delta;
- tab_b_->SetBounds(Round(new_x), tab_b_->GetY(), tab_b_->GetWidth(),
- tab_b_->GetHeight());
-
- tabstrip_->SchedulePaint();
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const { return kReorderAnimationDurationMs; }
-
- private:
- // The two tabs being exchanged.
- Tab* tab_a_;
- Tab* tab_b_;
-
- // ...and their bounds.
- gfx::Rect start_tab_a_bounds_;
- gfx::Rect start_tab_b_bounds_;
-
- DISALLOW_EVIL_CONSTRUCTORS(MoveTabAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Handles the animated resize layout of the entire TabStrip from one width
-// to another.
-class ResizeLayoutAnimation : public TabStrip::TabAnimation {
- public:
- explicit ResizeLayoutAnimation(TabStrip* tabstrip)
- : TabAnimation(tabstrip, RESIZE) {
- int tab_count = tabstrip->GetTabCount();
- GenerateStartAndEndWidths(tab_count, tab_count);
- InitStartState();
- }
- virtual ~ResizeLayoutAnimation() {
- }
-
- // Overridden from AnimationDelegate:
- virtual void AnimationEnded(const Animation* animation) {
- tabstrip_->resize_layout_scheduled_ = false;
- TabStrip::TabAnimation::AnimationEnded(animation);
- }
-
- protected:
- // Overridden from TabStrip::TabAnimation:
- virtual int GetDuration() const {
- return kResizeLayoutAnimationDurationMs;
- }
-
- virtual double GetWidthForTab(int index) const {
- if (tabstrip_->GetTabAt(index)->IsSelected()) {
- double delta = end_selected_width_ - start_selected_width_;
- return start_selected_width_ + (delta * animation_.GetCurrentValue());
- }
- double delta = end_unselected_width_ - start_unselected_width_;
- return start_unselected_width_ + (delta * animation_.GetCurrentValue());
- }
-
- private:
- // We need to start from the current widths of the Tabs as they were last
- // laid out, _not_ the last known good state, which is what'll be done if we
- // don't measure the Tab sizes here and just go with the default TabAnimation
- // behavior...
- void InitStartState() {
- for (int i = 0; i < tabstrip_->GetTabCount(); ++i) {
- Tab* current_tab = tabstrip_->GetTabAt(i);
- if (current_tab->IsSelected()) {
- start_selected_width_ = current_tab->GetWidth();
- } else {
- start_unselected_width_ = current_tab->GetWidth();
- }
- }
- }
-
- DISALLOW_EVIL_CONSTRUCTORS(ResizeLayoutAnimation);
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, public:
-
-TabStrip::TabStrip(TabStripModel* model)
- : model_(model),
- resize_layout_factory_(this),
- added_as_message_loop_observer_(false),
- resize_layout_scheduled_(false),
- current_unselected_width_(Tab::GetStandardSize().width()),
- current_selected_width_(Tab::GetStandardSize().width()),
- available_width_for_tabs_(-1) {
- Init();
-}
-
-TabStrip::~TabStrip() {
- // TODO(beng): (1031854) Restore this line once XPFrame/VistaFrame are dead.
- //model_->RemoveObserver(this);
-
- // TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug.
- drag_controller_.reset(NULL);
-
- // 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();
-}
-
-int TabStrip::GetPreferredHeight() {
- CSize preferred_size;
- GetPreferredSize(&preferred_size);
- return preferred_size.cy;
-}
-
-bool TabStrip::HasAvailableDragActions() const {
- return model_->delegate()->GetDragActions() != 0;
-}
-
-void TabStrip::ShowApplicationMenu(const gfx::Point& p) {
- TabStripModelDelegate* delegate = model_->delegate();
- if (delegate)
- delegate->ShowApplicationMenu(p);
-}
-
-bool TabStrip::CanProcessInputEvents() const {
- return IsAnimating() == NULL;
-}
-
-bool TabStrip::PointIsWithinWindowCaption(const CPoint& point) {
- ChromeViews::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;
-
- // If the point is within the bounds of a Tab, the point can be considered
- // part of the caption if there are no available drag operations for the Tab.
- if (v->GetClassName() == Tab::kTabClassName && !HasAvailableDragActions())
- 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;
-}
-
-bool TabStrip::IsCompatibleWith(TabStrip* other) {
- return model_->profile() == other->model()->profile();
-}
-
-bool TabStrip::IsAnimating() const {
- return active_animation_.get() != NULL;
-}
-
-void TabStrip::DestroyDragController() {
- if (IsDragSessionActive())
- drag_controller_.reset(NULL);
-}
-
-void TabStrip::DestroyDraggedSourceTab(Tab* tab) {
- // We could be running an animation that references this Tab.
- if (active_animation_.get())
- active_animation_->Stop();
- // Make sure we leave the tab_data_ vector in a consistent state, otherwise
- // we'll be pointing to tabs that have been deleted and removed from the
- // child view list.
- std::vector<TabData>::iterator it = tab_data_.begin();
- for (; it != tab_data_.end(); ++it) {
- if (it->tab == tab) {
- NOTREACHED() << "Leaving in an inconsistent state!";
- tab_data_.erase(it);
- break;
- }
- }
- tab->GetParent()->RemoveChildView(tab);
- delete tab;
- // Force a layout here, because if we've just quickly drag detached a Tab,
- // the stopping of the active animation above may have left the TabStrip in a
- // bad (visual) state.
- Layout();
-}
-
-gfx::Rect TabStrip::GetIdealBounds(int index) {
- DCHECK(index >= 0 && index < GetTabCount());
- return tab_data_.at(index).ideal_bounds;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, ChromeViews::View overrides:
-
-void TabStrip::PaintChildren(ChromeCanvas* canvas) {
- // Paint the tabs in reverse order, so they stack to the left.
- Tab* selected_tab = NULL;
- for (int i = GetTabCount() - 1; i >= 0; --i) {
- Tab* tab = GetTabAt(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->IsSelected()) {
- tab->ProcessPaint(canvas);
- } else {
- selected_tab = tab;
- }
- }
-
- if (win_util::ShouldUseVistaFrame()) {
- // Make sure unselected tabs are somewhat transparent.
- SkPaint paint;
- paint.setColor(SkColorSetARGB(200, 255, 255, 255));
- paint.setPorterDuffXfermode(SkPorterDuff::kDstIn_Mode);
- paint.setStyle(SkPaint::kFill_Style);
- canvas->FillRectInt(
- 0, 0, GetWidth(),
- GetHeight() - 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);
-}
-
-void TabStrip::DidChangeBounds(const CRect& prev, const CRect& curr) {
- Layout();
-}
-
-// Overridden to support automation. See automation_proxy_uitest.cc.
-ChromeViews::View* TabStrip::GetViewByID(int view_id) const {
- if (GetTabCount() > 0) {
- if (view_id == VIEW_ID_TAB_LAST) {
- return GetTabAt(GetTabCount() - 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 < GetTabCount()) {
- return GetTabAt(index);
- } else {
- return NULL;
- }
- }
- }
-
- return View::GetViewByID(view_id);
-}
-
-void TabStrip::Layout() {
- // Called from:
- // - window resize
- // - animation completion
- if (active_animation_.get())
- active_animation_->Stop();
- GenerateIdealBounds();
- int tab_count = GetTabCount();
- int tab_right = 0;
- for (int i = 0; i < tab_count; ++i) {
- const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds;
- GetTabAt(i)->SetBounds(bounds.x(), bounds.y(), bounds.width(),
- bounds.height());
- tab_right = bounds.right() + kTabHOffset;
- }
- LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_);
- SchedulePaint();
-}
-
-void TabStrip::GetPreferredSize(CSize* preferred_size) {
- DCHECK(preferred_size);
- preferred_size->cx = 0;
- preferred_size->cy = Tab::GetMinimumSize().height();
-}
-
-void TabStrip::OnDragEntered(const DropTargetEvent& event) {
- 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;
-
- if (drop_before) {
- UserMetrics::RecordAction(L"Tab_DropURLBetweenTabs", model_->profile());
-
- // Insert a new tab.
- TabContents* contents =
- model_->delegate()->CreateTabContentsForURL(
- url, model_->profile(), PageTransition::TYPED, false, NULL);
- model_->AddTabContents(contents, drop_index, PageTransition::GENERATED,
- true);
- } else {
- UserMetrics::RecordAction(L"Tab_DropURLOnTab", model_->profile());
-
- model_->GetTabContentsAt(drop_index)->controller()->
- LoadURL(url, PageTransition::GENERATED);
- model_->SelectTabContentsAt(drop_index, true);
- }
-
- return GetDropEffect(event);
-}
-
-bool TabStrip::GetAccessibleRole(VARIANT* role) {
- DCHECK(role);
-
- role->vt = VT_I4;
- role->lVal = ROLE_SYSTEM_GROUPING;
- return true;
-}
-
-bool TabStrip::GetAccessibleName(std::wstring* name) {
- if (!accessible_name_.empty()) {
- (*name).assign(accessible_name_);
- return true;
- }
- return false;
-}
-
-void TabStrip::SetAccessibleName(const std::wstring& name) {
- accessible_name_.assign(name);
-}
-
-ChromeViews::View* TabStrip::GetViewForPoint(const CPoint& point) {
- return GetViewForPoint(point, false);
-}
-
-ChromeViews::View* TabStrip::GetViewForPoint(const CPoint& point,
- bool can_create_floating) {
- // Return any view that isn't a Tab or this TabStrip immediately. We don't
- // want to interfere.
- ChromeViews::View* v = View::GetViewForPoint(point, can_create_floating);
- if (v && v != this && v->GetClassName() != Tab::kTabClassName)
- 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.
- int tab_count = GetTabCount();
- for (int i = 0; i < tab_count; ++i) {
- Tab* next_tab = i < (tab_count - 1) ? GetTabAt(i + 1) : NULL;
- if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point))
- return next_tab;
- Tab* tab = GetTabAt(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;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, TabStripModelObserver implementation:
-
-void TabStrip::TabInsertedAt(TabContents* contents,
- int index,
- bool foreground) {
- DCHECK(contents);
- DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index));
-
- if (active_animation_.get())
- active_animation_->Stop();
-
- bool contains_tab = false;
- Tab* tab = NULL;
- // First see if this Tab is one that was dragged out of this TabStrip and is
- // now being dragged back in. In this case, the DraggedTabController actually
- // has the Tab already constructed and we can just insert it into our list
- // again.
- if (IsDragSessionActive()) {
- tab = drag_controller_->GetDragSourceTabForContents(contents);
- if (tab) {
- // If the Tab was detached, it would have been animated closed but not
- // removed, so we need to reset this property.
- tab->set_closing(false);
- tab->ValidateLoadingAnimation(TabRenderer::ANIMATION_NONE);
- tab->SetVisible(true);
- }
-
- // See if we're already in the list. We don't want to add ourselves twice.
- std::vector<TabData>::const_iterator iter = tab_data_.begin();
- for (; iter != tab_data_.end() && !contains_tab; ++iter) {
- if (iter->tab == tab)
- contains_tab = true;
- }
- }
-
- // Otherwise we need to make a new Tab.
- if (!tab)
- tab = new Tab(this);
-
- // Only insert if we're not already in the list.
- if (!contains_tab) {
- if (index == TabStripModel::kNoTab) {
- TabData d = { tab, gfx::Rect() };
- tab_data_.push_back(d);
- tab->UpdateData(contents);
- } else {
- TabData d = { tab, gfx::Rect() };
- tab_data_.insert(tab_data_.begin() + index, d);
- tab->UpdateData(contents);
- }
- }
-
- // We only add the tab to the child list if it's not already - an invisible
- // tab maintained by the DraggedTabController will already be parented.
- if (!tab->GetParent())
- 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 (GetTabCount() > 1 && IsWindowVisible(GetViewContainer()->GetHWND())) {
- StartInsertTabAnimation(index);
- } else {
- Layout();
- }
-}
-
-void TabStrip::TabDetachedAt(TabContents* contents, int index) {
- if (CanUpdateDisplay()) {
- GenerateIdealBounds();
- StartRemoveTabAnimation(index, contents);
- // Have to do this _after_ calling StartRemoveTabAnimation, so that any
- // previous remove is completed fully and index is valid in sync with the
- // model index.
- GetTabAt(index)->set_closing(true);
- }
-}
-
-void TabStrip::TabSelectedAt(TabContents* old_contents,
- TabContents* new_contents,
- int index,
- bool user_gesture) {
- DCHECK(index >= 0 && index < GetTabCount());
- if (CanUpdateDisplay()) {
- // 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() && (!resize_layout_scheduled_ || tiny_tabs)) {
- Layout();
- } else {
- SchedulePaint();
- }
- }
-}
-
-void TabStrip::TabMoved(TabContents* contents, int from_index, int to_index) {
- Tab* tab = GetTabAt(from_index);
- Tab* other_tab = GetTabAt(to_index);
- tab_data_.erase(tab_data_.begin() + from_index);
- TabData data = {tab, gfx::Rect()};
- tab_data_.insert(tab_data_.begin() + to_index, data);
- GenerateIdealBounds();
- StartMoveTabAnimation(from_index, to_index);
-}
-
-void TabStrip::TabChangedAt(TabContents* contents, int index) {
- // Index is in terms of the model. Need to make sure we adjust that index in
- // case we have an animation going.
- Tab* tab = GetTabAtAdjustForAnimation(index);
- tab->UpdateData(contents);
- tab->UpdateFromModel();
-}
-
-void TabStrip::TabValidateAnimations() {
- if (model_->TabsAreLoading()) {
- if (!loading_animation_timer_.IsRunning()) {
- // Loads are happening, and the timer isn't running, so start it.
- loading_animation_timer_.Start(
- TimeDelta::FromMilliseconds(kLoadingAnimationFrameTimeMs), this,
- &TabStrip::LoadingAnimationCallback);
- }
- } else {
- if (loading_animation_timer_.IsRunning()) {
- loading_animation_timer_.Stop();
- // Loads are now complete, update the state if a task was scheduled.
- LoadingAnimationCallback();
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, Tab::Delegate implementation:
-
-bool TabStrip::IsTabSelected(const Tab* tab) const {
- if (tab->closing())
- return false;
-
- int tab_count = GetTabCount();
- for (int i = 0, index = 0; i < tab_count; ++i, ++index) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab->closing())
- --index;
- if (current_tab == tab)
- return index == model_->selected_index();
- }
- return false;
-}
-
-void TabStrip::SelectTab(Tab* tab) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- model_->SelectTabContentsAt(index, true);
-}
-
-void TabStrip::CloseTab(Tab* tab) {
- int tab_index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(tab_index)) {
- TabContents* contents = model_->GetTabContentsAt(tab_index);
- if (contents)
- UserMetrics::RecordAction(L"CloseTab_Mouse", contents->profile());
- Tab* last_tab = GetTabAt(GetTabCount() - 1);
- // Limit the width available to the TabStrip for laying out Tabs, so that
- // Tabs are not resized until a later time (when the mouse pointer leaves
- // the TabStrip).
- available_width_for_tabs_ = GetAvailableWidthForTabs(last_tab);
- resize_layout_scheduled_ = true;
- AddMessageLoopObserver();
- model_->CloseTabContentsAt(tab_index);
- }
-}
-
-bool TabStrip::IsCommandEnabledForTab(
- TabStripModel::ContextMenuCommand command_id, const Tab* tab) const {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- return model_->IsContextMenuCommandEnabled(index, command_id);
- return false;
-}
-
-void TabStrip::ExecuteCommandForTab(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index))
- model_->ExecuteContextMenuCommand(index, command_id);
-}
-
-void TabStrip::StartHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) {
- if (command_id == TabStripModel::CommandCloseTabsOpenedBy) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index)) {
- std::vector<int> indices = model_->GetIndexesOpenedBy(index);
- std::vector<int>::const_iterator iter = indices.begin();
- for (; iter != indices.end(); ++iter) {
- int current_index = *iter;
- DCHECK(current_index >= 0 && current_index < GetTabCount());
- Tab* current_tab = GetTabAt(current_index);
- current_tab->StartPulse();
- }
- }
- } else if (command_id == TabStripModel::CommandCloseTabsToRight) {
- int index = GetIndexOfTab(tab);
- if (model_->ContainsIndex(index)) {
- for (int i = index + 1; i < GetTabCount(); ++i) {
- Tab* current_tab = GetTabAt(i);
- current_tab->StartPulse();
- }
- }
- } else if (command_id == TabStripModel::CommandCloseOtherTabs) {
- for (int i = 0; i < GetTabCount(); ++i) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab != tab)
- current_tab->StartPulse();
- }
- }
-}
-
-void TabStrip::StopHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab) {
- if (command_id == TabStripModel::CommandCloseTabsOpenedBy ||
- command_id == TabStripModel::CommandCloseTabsToRight ||
- command_id == TabStripModel::CommandCloseOtherTabs) {
- // Just tell all Tabs to stop pulsing - it's safe.
- StopAllHighlighting();
- }
-}
-
-void TabStrip::StopAllHighlighting() {
- for (int i = 0; i < GetTabCount(); ++i)
- GetTabAt(i)->StopPulse();
-}
-
-void TabStrip::MaybeStartDrag(Tab* tab, const ChromeViews::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())
- return;
- drag_controller_.reset(new DraggedTabController(tab, this));
- drag_controller_->CaptureDragInfo(gfx::Point(event.GetX(), event.GetY()));
-}
-
-void TabStrip::ContinueDrag(const ChromeViews::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())
- drag_controller_->Drag();
-}
-
-void TabStrip::EndDrag(bool canceled) {
- if (drag_controller_.get())
- drag_controller_->EndDrag(canceled);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, ChromeViews::BaseButton::ButtonListener implementation:
-
-void TabStrip::ButtonPressed(ChromeViews::BaseButton* sender) {
- if (sender == newtab_button_)
- model_->AddBlankTab(true);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, MessageLoop::Observer implementation:
-
-void TabStrip::WillProcessMessage(const MSG& msg) {
-}
-
-void TabStrip::DidProcessMessage(const MSG& msg) {
- // We spy on three different Windows messages here to see if the mouse has
- // moved out of the bounds of the tabstrip, which we use as our cue to kick
- // of the resize animation. The messages are:
- //
- // WM_MOUSEMOVE:
- // For when the mouse moves from the tabstrip over into the rest of the
- // browser UI, i.e. within the bounds of the same windows HWND.
- // WM_MOUSELEAVE:
- // For when the mouse moves very rapidly from a tab closed in the middle of
- // the tabstrip (_not_ the end) out of the bounds of the browser's HWND and
- // over some other HWND.
- // WM_NCMOUSELEAVE:
- // For when the mouse moves very rapidly from the end of the tabstrip (when
- // the last tab is closed and the mouse is left floating over the title
- // bar). Because the empty area of the tabstrip at the end of the title bar
- // is registered by the ChromeFrame as part of the "caption" area of the
- // window (the frame's OnNCHitTest method returns HTCAPTION for this
- // region), the frame's HWND receives a WM_MOUSEMOVE message immediately,
- // because as far as it is concerned the mouse has _left_ the client area
- // of the window (and is now over the non-client area). To be notified
- // again when the mouse leaves the _non-client_ area, we use the
- // WM_NCMOUSELEAVE message, which causes us to re-evaluate the cursor
- // position and correctly resize the tabstrip.
- //
- switch (msg.message) {
- case WM_MOUSEMOVE:
- case WM_MOUSELEAVE:
- case WM_NCMOUSELEAVE:
- if (!IsCursorInTabStripZone()) {
- // Mouse moved outside the tab slop zone, start a timer to do a resize
- // layout after a short while...
- if (resize_layout_factory_.empty()) {
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- resize_layout_factory_.NewRunnableMethod(
- &TabStrip::ResizeLayoutTabs),
- kResizeTabsTimeMs);
- }
- } else {
- // Mouse moved quickly out of the tab strip and then into it again, so
- // cancel the timer so that the strip doesn't move when the mouse moves
- // back over it.
- resize_layout_factory_.RevokeAll();
- }
- break;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// TabStrip, private:
-
-void TabStrip::Init() {
- model_->AddObserver(this);
- newtab_button_ = new ChromeViews::Button;
- newtab_button_->SetListener(this, TabStripModel::kNoTab);
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- SkBitmap* bitmap;
-
- bitmap = rb.GetBitmapNamed(IDR_NEWTAB_BUTTON);
- newtab_button_->SetImage(ChromeViews::Button::BS_NORMAL, bitmap);
- newtab_button_->SetImage(ChromeViews::Button::BS_PUSHED,
- rb.GetBitmapNamed(IDR_NEWTAB_BUTTON_P));
- newtab_button_->SetImage(ChromeViews::Button::BS_HOT,
- rb.GetBitmapNamed(IDR_NEWTAB_BUTTON_H));
-
- newtab_button_size_.SetSize(bitmap->width(), bitmap->height());
- actual_newtab_button_size_ = newtab_button_size_;
-
- newtab_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_NEWTAB));
- AddChildView(newtab_button_);
-
- 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();
- }
-}
-
-Tab* TabStrip::GetTabAt(int index) const {
- DCHECK(index >= 0 && index < GetTabCount());
- return tab_data_.at(index).tab;
-}
-
-Tab* TabStrip::GetTabAtAdjustForAnimation(int index) const {
- if (active_animation_.get() &&
- active_animation_->type() == TabAnimation::REMOVE &&
- index >=
- static_cast<RemoveTabAnimation*>(active_animation_.get())->index()) {
- index++;
- }
- return GetTabAt(index);
-}
-
-int TabStrip::GetTabCount() const {
- return static_cast<int>(tab_data_.size());
-}
-
-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,
- double* unselected_width,
- double* selected_width) const {
- const double min_unselected_width = Tab::GetMinimumSize().width();
- const double min_selected_width = Tab::GetMinimumSelectedSize().width();
- if (tab_count == 0) {
- // Return immediately to avoid divide-by-zero below.
- *unselected_width = min_unselected_width;
- *selected_width = min_selected_width;
- return;
- }
-
- // Determine how much space we can actually allocate to tabs.
- int available_width;
- if (available_width_for_tabs_ < 0) {
- available_width = GetWidth();
- available_width -= (kNewTabButtonHOffset + newtab_button_size_.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_;
- }
-
- // 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() {
- resize_layout_factory_.RevokeAll();
-
- // It is critically important that this is unhooked here, otherwise we will
- // keep spying on messages forever.
- RemoveMessageLoopObserver();
-
- available_width_for_tabs_ = -1;
- double unselected, selected;
- GetDesiredTabWidths(GetTabCount(), &unselected, &selected);
- Tab* first_tab = GetTabAt(0);
- 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->GetWidth() - w) > 1)
- StartResizeLayoutAnimation();
-}
-
-bool TabStrip::IsCursorInTabStripZone() {
- CRect bounds;
- GetLocalBounds(&bounds, true);
- CPoint tabstrip_topleft = bounds.TopLeft();
- View::ConvertPointToScreen(this, &tabstrip_topleft);
- bounds.MoveToXY(tabstrip_topleft);
- bounds.bottom += kTabStripAnimationVSlop;
-
- CPoint cursor_point;
- GetCursorPos(&cursor_point);
-
- return !!bounds.PtInRect(cursor_point);
-}
-
-void TabStrip::AddMessageLoopObserver() {
- if (!added_as_message_loop_observer_) {
- MessageLoopForUI::current()->AddObserver(this);
- added_as_message_loop_observer_ = true;
- }
-}
-
-void TabStrip::RemoveMessageLoopObserver() {
- if (added_as_message_loop_observer_) {
- MessageLoopForUI::current()->RemoveObserver(this);
- added_as_message_loop_observer_ = false;
- }
-}
-
-void TabStrip::LoadingAnimationCallback() {
- for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab->closing()) {
- --index;
- } else {
- TabContents* contents = model_->GetTabContentsAt(index);
- if (!contents || !contents->is_loading()) {
- current_tab->ValidateLoadingAnimation(Tab::ANIMATION_NONE);
- } else if (contents->response_started()) {
- current_tab->ValidateLoadingAnimation(Tab::ANIMATION_WAITING);
- } else {
- current_tab->ValidateLoadingAnimation(Tab::ANIMATION_LOADING);
- }
- }
- }
-
- // Make sure the model delegates updates the animation as well.
- TabStripModelDelegate* delegate;
- if (model_ && (delegate = model_->delegate()))
- delegate->ValidateLoadingAnimations();
-}
-
-gfx::Rect TabStrip::GetDropBounds(int drop_index,
- bool drop_before,
- bool* is_beneath) {
- DCHECK(drop_index != -1);
- int center_x;
- if (drop_index < GetTabCount()) {
- Tab* tab = GetTabAt(drop_index);
- if (drop_before)
- center_x = tab->GetX() - (kTabHOffset / 2);
- else
- center_x = tab->GetX() + (tab->GetWidth() / 2);
- } else {
- Tab* last_tab = GetTabAt(drop_index - 1);
- center_x = last_tab->GetX() + last_tab->GetWidth() + (kTabHOffset / 2);
- }
-
- // Mirror the center point if necessary.
- center_x = MirroredXCoordinateInsideView(center_x);
-
- // Determine the screen bounds.
- CPoint 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.
- gfx::Rect monitor_bounds = win_util::GetMonitorBoundsForRect(drop_bounds);
- *is_beneath = (monitor_bounds.IsEmpty() ||
- !monitor_bounds.Contains(drop_bounds));
- if (*is_beneath)
- drop_bounds.Offset(0, drop_bounds.height() + GetHeight());
-
- 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.GetX());
- for (int i = 0; i < GetTabCount(); ++i) {
- Tab* tab = GetTabAt(i);
- const int tab_max_x = tab->GetX() + tab->GetWidth();
- const int hot_width = tab->GetWidth() / 3;
- if (x < tab_max_x) {
- if (x < tab->GetX() + 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(GetTabCount(), true);
-}
-
-void TabStrip::SetDropIndex(int index, bool drop_before) {
- if (index == -1) {
- if (drop_info_.get())
- drop_info_.reset(NULL);
- return;
- }
-
- if (drop_info_.get() && drop_info_->drop_index == index &&
- drop_info_->drop_before == drop_before) {
- return;
- }
-
- bool is_beneath;
- gfx::Rect drop_bounds = GetDropBounds(index, drop_before, &is_beneath);
-
- if (!drop_info_.get()) {
- drop_info_.reset(new DropInfo(index, drop_before, !is_beneath));
- } else {
- drop_info_->drop_index = 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.
-
- drop_info_->arrow_window->SetWindowPos(
- HWND_TOPMOST, drop_bounds.x(), drop_bounds.y(), drop_bounds.width(),
- drop_bounds.height(), SWP_NOACTIVATE | SWP_SHOWWINDOW);
-}
-
-int TabStrip::GetDropEffect(const ChromeViews::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_window = new ChromeViews::HWNDViewContainer();
- 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);
-
- arrow_view = new ChromeViews::ImageView;
- arrow_view->SetImage(GetDropArrowImage(point_down));
-
- arrow_window->Init(
- NULL,
- gfx::Rect(0, 0, drop_indicator_width, drop_indicator_height),
- true);
- 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 tab_count = GetTabCount();
- double unselected, selected;
- GetDesiredTabWidths(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;
- for (int i = 0; i < tab_count; ++i) {
- Tab* tab = GetTabAt(i);
- double tab_width = unselected;
- if (tab->IsSelected())
- tab_width = selected;
- double end_of_tab = tab_x + tab_width;
- int rounded_tab_x = Round(tab_x);
- gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
- tab_height);
- tab_data_.at(i).ideal_bounds = state;
- tab_x = end_of_tab + kTabHOffset;
- }
-}
-
-void TabStrip::LayoutNewTabButton(double last_tab_right,
- double unselected_width) {
- int delta = abs(Round(unselected_width) - Tab::GetStandardSize().width());
- if (delta > 1 && !resize_layout_scheduled_) {
- // 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.
- newtab_button_->SetBounds(GetWidth() - newtab_button_size_.width(),
- kNewTabButtonVOffset,
- newtab_button_size_.width(),
- newtab_button_size_.height());
- } else {
- newtab_button_->SetBounds(
- Round(last_tab_right - kTabHOffset) + kNewTabButtonHOffset,
- kNewTabButtonVOffset, newtab_button_size_.width(),
- newtab_button_size_.height());
- }
-}
-
-// Called from:
-// - animation tick
-void TabStrip::AnimationLayout(double unselected_width) {
- int tab_height = Tab::GetStandardSize().height();
- double tab_x = 0;
- for (int i = 0; i < GetTabCount(); ++i) {
- TabAnimation* animation = active_animation_.get();
- double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i);
- double end_of_tab = tab_x + tab_width;
- int rounded_tab_x = Round(tab_x);
- Tab* tab = GetTabAt(i);
- tab->SetBounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x,
- tab_height);
- tab_x = end_of_tab + kTabHOffset;
- }
- LayoutNewTabButton(tab_x, unselected_width);
- SchedulePaint();
-}
-
-void TabStrip::StartResizeLayoutAnimation() {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new ResizeLayoutAnimation(this));
- active_animation_->Start();
-}
-
-void TabStrip::StartInsertTabAnimation(int index) {
- // The TabStrip can now use its entire width to lay out Tabs.
- available_width_for_tabs_ = -1;
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new InsertTabAnimation(this, index));
- active_animation_->Start();
-}
-
-void TabStrip::StartRemoveTabAnimation(int index, TabContents* contents) {
- if (active_animation_.get()) {
- // Some animations (e.g. MoveTabAnimation) cause there to be a Layout when
- // they're completed (which includes canceled). Since |tab_data_| is now
- // inconsistent with TabStripModel, doing this Layout will crash now, so
- // we ask the MoveTabAnimation to skip its Layout (the state will be
- // corrected by the RemoveTabAnimation we're about to initiate).
- active_animation_->set_layout_on_completion(false);
- active_animation_->Stop();
- }
- active_animation_.reset(new RemoveTabAnimation(this, index, contents));
- active_animation_->Start();
-}
-
-void TabStrip::StartMoveTabAnimation(int from_index, int to_index) {
- if (active_animation_.get())
- active_animation_->Stop();
- active_animation_.reset(new MoveTabAnimation(this, from_index, to_index));
- active_animation_->Start();
-}
-
-bool TabStrip::CanUpdateDisplay() {
- // Don't bother laying out/painting when we're closing all tabs.
- if (model_->closing_all()) {
- // Make sure any active animation is ended, too.
- if (active_animation_.get())
- active_animation_->Stop();
- return false;
- }
- return true;
-}
-
-void TabStrip::FinishAnimation(TabStrip::TabAnimation* animation,
- bool layout) {
- active_animation_.reset(NULL);
- if (layout)
- Layout();
-}
-
-int TabStrip::GetIndexOfTab(const Tab* tab) const {
- for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) {
- Tab* current_tab = GetTabAt(i);
- if (current_tab->closing()) {
- --index;
- } else if (current_tab == tab) {
- return index;
- }
- }
- return -1;
-}
-
-int TabStrip::GetAvailableWidthForTabs(Tab* last_tab) const {
- return last_tab->GetX() + last_tab->GetWidth();
-}
-
-bool TabStrip::IsPointInTab(Tab* tab, const CPoint& point_in_tabstrip_coords) {
- CPoint 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/tabs/tab_strip.h b/chrome/browser/tabs/tab_strip.h
deleted file mode 100644
index 11f6f64..0000000
--- a/chrome/browser/tabs/tab_strip.h
+++ /dev/null
@@ -1,373 +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.
-
-#ifndef CHROME_BROWSER_TABS_TAB_STRIP_H__
-#define CHROME_BROWSER_TABS_TAB_STRIP_H__
-
-#include "base/gfx/point.h"
-#include "chrome/browser/tabs/tab.h"
-#include "chrome/browser/tabs/tab_strip_model.h"
-#include "chrome/views/button.h"
-#include "chrome/views/hwnd_view_container.h"
-#include "chrome/views/menu.h"
-#include "chrome/views/view.h"
-
-class DraggedTabController;
-class ScopedMouseCloseWidthCalculator;
-class TabStripModel;
-
-namespace ChromeViews {
-class ImageView;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// 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 ChromeViews::View,
- public TabStripModelObserver,
- public Tab::TabDelegate,
- public ChromeViews::Button::ButtonListener,
- public MessageLoopForUI::Observer {
- public:
- TabStrip(TabStripModel* model);
- virtual ~TabStrip();
-
- // Returns the preferred height of this TabStrip. This is based on the
- // typical height of its constituent tabs.
- int GetPreferredHeight();
-
- // 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.
- bool HasAvailableDragActions() const;
-
- // Ask the delegate to show the application menu at the provided point.
- // The point is in screen coordinate system.
- void ShowApplicationMenu(const gfx::Point& p);
-
- // Returns true if the TabStrip can accept input events. This returns false
- // when the TabStrip is animating to a new state and as such the user should
- // not be allowed to interact with the TabStrip.
- bool CanProcessInputEvents() const;
-
- // Returns true if the specified point (in TabStrip coordinates) is within a
- // portion of the TabStrip that should be treated as the containing Window's
- // titlebar for dragging purposes.
- // TODO(beng): (Cleanup) should be const, but GetViewForPoint isn't, so fie!
- bool PointIsWithinWindowCaption(const CPoint& point);
-
- // Return true if this tab strip is compatible with the provided tab strip.
- // Compatible tab strips can transfer tabs during drag and drop.
- bool IsCompatibleWith(TabStrip* other);
-
- // Returns true if Tabs in this TabStrip are currently changing size or
- // position.
- bool IsAnimating() const;
-
- // Accessors for the model and individual Tabs.
- TabStripModel* model() { return model_; }
-
- // Returns true if there is an active drag session.
- bool IsDragSessionActive() const { return drag_controller_.get() != NULL; }
-
- // Aborts any active drag session. This is called from XP/VistaFrame's
- // end session handler to make sure there are no drag sessions in flight that
- // could prevent the frame from being closed right away.
- void AbortActiveDragSession() { EndDrag(true); }
-
- // Destroys the active drag controller.
- void DestroyDragController();
-
- // Removes the drag source Tab from this TabStrip, and deletes it.
- void DestroyDraggedSourceTab(Tab* tab);
-
- // Retrieve the ideal bounds for the Tab at the specified index.
- gfx::Rect GetIdealBounds(int index);
-
- // ChromeViews::View overrides:
- virtual void PaintChildren(ChromeCanvas* canvas);
- virtual void DidChangeBounds(const CRect& previous, const CRect& current);
- virtual ChromeViews::View* GetViewByID(int id) const;
- virtual void Layout();
- virtual void GetPreferredSize(CSize* preferred_size);
- // 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 ChromeViews::DropTargetEvent& event);
- virtual int OnDragUpdated(const ChromeViews::DropTargetEvent& event);
- virtual void OnDragExited();
- virtual int OnPerformDrop(const ChromeViews::DropTargetEvent& event);
- virtual bool GetAccessibleRole(VARIANT* role);
- virtual bool GetAccessibleName(std::wstring* name);
- virtual void SetAccessibleName(const std::wstring& name);
- virtual ChromeViews::View* GetViewForPoint(const CPoint& point);
- virtual ChromeViews::View* GetViewForPoint(const CPoint& point,
- bool can_create_floating);
-
- protected:
- // TabStripModelObserver implementation:
- virtual void TabInsertedAt(TabContents* contents,
- int index,
- bool foreground);
- virtual void TabDetachedAt(TabContents* contents, int index);
- virtual void TabSelectedAt(TabContents* old_contents,
- TabContents* contents,
- int index,
- bool user_gesture);
- virtual void TabMoved(TabContents* contents, int from_index, int to_index);
- virtual void TabChangedAt(TabContents* contents, int index);
- virtual void TabValidateAnimations();
-
- // Tab::Delegate implementation:
- virtual bool IsTabSelected(const Tab* tab) const;
- virtual void SelectTab(Tab* tab);
- virtual void CloseTab(Tab* tab);
- virtual bool IsCommandEnabledForTab(
- TabStripModel::ContextMenuCommand command_id, const Tab* tab) const;
- virtual void ExecuteCommandForTab(
- TabStripModel::ContextMenuCommand command_id, Tab* tab);
- virtual void StartHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab);
- virtual void StopHighlightTabsForCommand(
- TabStripModel::ContextMenuCommand command_id, Tab* tab);
- virtual void StopAllHighlighting();
- virtual void MaybeStartDrag(Tab* tab,
- const ChromeViews::MouseEvent& event);
- virtual void ContinueDrag(const ChromeViews::MouseEvent& event);
- virtual void EndDrag(bool canceled);
-
- // ChromeViews::Button::ButtonListener implementation:
- virtual void ButtonPressed(ChromeViews::BaseButton* sender);
-
- // MessageLoop::Observer implementation:
- virtual void WillProcessMessage(const MSG& msg);
- virtual void DidProcessMessage(const MSG& msg);
-
- private:
- friend class DraggedTabController;
- friend class InsertTabAnimation;
- friend class MoveTabAnimation;
- friend class RemoveTabAnimation;
- friend class ResizeLayoutAnimation;
- friend class SuspendAnimationsTask;
- friend class TabAnimation;
-
- TabStrip();
- void Init();
-
- // Retrieves the Tab at the specified index. Take care in using this, you may
- // need to use GetTabAtAdjustForAnimation.
- Tab* GetTabAt(int 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 GetTabAt if the index comes from the model.
- Tab* GetTabAtAdjustForAnimation(int index) const;
-
- // Gets the number of Tabs in the collection.
- int GetTabCount() 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.
- void GetDesiredTabWidths(int tab_count,
- double* unselected_width,
- double* selected_width) const;
-
- // Perform an animated resize-relayout of the TabStrip immediately.
- void ResizeLayoutTabs();
-
- // Returns whether or not the cursor is currently in the "tab strip zone"
- // which is defined as the region above the TabStrip and a bit below it.
- // Note: this method cannot be const because |ConvertPointToScreen| is not.
- // #@*($&(#!!!
- bool IsCursorInTabStripZone();
-
- // 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();
-
- // Called to update the frame of the Loading animations.
- void LoadingAnimationCallback();
-
- // -- 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 ChromeViews::DropTargetEvent& event);
-
- // Sets the location of the drop, repainting as necessary.
- void SetDropIndex(int 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 ChromeViews::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();
-
- // Lays out the New Tab button, assuming the right edge of the last Tab on
- // the TabStrip at |last_tab_right|.
- void LayoutNewTabButton(double last_tab_right, double unselected_width);
-
- // A generic Layout method for various classes of TabStrip animations,
- // including Insert, Remove and Resize Layout cases/
- void AnimationLayout(double unselected_width);
-
- // Starts various types of TabStrip animations.
- void StartResizeLayoutAnimation();
- void StartInsertTabAnimation(int index);
- void StartRemoveTabAnimation(int index, TabContents* contents);
- void StartMoveTabAnimation(int from_index, int to_index);
-
- // Returns true if detach or select changes in the model should be reflected
- // in the TabStrip. This returns false if we're closing all tabs in the
- // TabStrip and so we should prevent updating. This is not const because we
- // use this as a signal to cancel any active animations.
- bool CanUpdateDisplay();
-
- // Notifies the TabStrip that the specified TabAnimation has completed.
- // Optionally a full Layout will be performed, specified by |layout|.
- class TabAnimation;
- void FinishAnimation(TabAnimation* animation, bool layout);
-
- // Finds the index of the TabContents corresponding to |tab| in our
- // associated TabStripModel, or -1 if there is none (e.g. the specified |tab|
- // is being animated closed).
- int GetIndexOfTab(const Tab* tab) const;
-
- // 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 CPoint& point_in_tabstrip_coords);
-
- // -- Member Variables ------------------------------------------------------
-
- // Our model.
- TabStripModel* model_;
-
- // A factory that is used to construct a delayed callback to the
- // ResizeLayoutTabsNow method.
- ScopedRunnableMethodFactory<TabStrip> resize_layout_factory_;
-
- // True if the TabStrip has already been added as a MessageLoop observer.
- bool added_as_message_loop_observer_;
-
- // True if a resize layout animation should be run a short delay after the
- // mouse exits the TabStrip.
- // TODO(beng): (Cleanup) this would be better named "needs_resize_layout_".
- bool resize_layout_scheduled_;
-
- // The timer used to update frames for the Loading Animation.
- base::RepeatingTimer<TabStrip> loading_animation_timer_;
-
- // The "New Tab" button.
- ChromeViews::Button* newtab_button_;
- gfx::Size newtab_button_size_;
- gfx::Size actual_newtab_button_size_;
-
- // 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_;
-
- // Storage of strings needed for accessibility.
- std::wstring accessible_name_;
-
- // 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.
- ChromeViews::HWNDViewContainer* arrow_window;
- ChromeViews::ImageView* arrow_view;
-
- private:
- DISALLOW_EVIL_CONSTRUCTORS(DropInfo);
- };
-
- // Valid for the lifetime of a drag over us.
- scoped_ptr<DropInfo> drop_info_;
-
- // The controller for a drag initiated from a Tab. Valid for the lifetime of
- // the drag session.
- scoped_ptr<DraggedTabController> drag_controller_;
-
- // The Tabs we contain, and their last generated "good" bounds.
- struct TabData {
- Tab* tab;
- gfx::Rect ideal_bounds;
- };
- std::vector<TabData> tab_data_;
-
- // The currently running animation.
- scoped_ptr<TabAnimation> active_animation_;
-
- DISALLOW_EVIL_CONSTRUCTORS(TabStrip);
-};
-
-#endif // CHROME_BROWSER_TABS_TAB_STRIP_H__
-