summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/tabs/dragged_tab_view.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/views/tabs/dragged_tab_view.cc')
-rw-r--r--chrome/browser/views/tabs/dragged_tab_view.cc244
1 files changed, 244 insertions, 0 deletions
diff --git a/chrome/browser/views/tabs/dragged_tab_view.cc b/chrome/browser/views/tabs/dragged_tab_view.cc
new file mode 100644
index 0000000..6e3fead
--- /dev/null
+++ b/chrome/browser/views/tabs/dragged_tab_view.cc
@@ -0,0 +1,244 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/views/tabs/dragged_tab_view.h"
+
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/browser/tab_contents.h"
+#include "chrome/browser/tabs/tab_strip_model.h"
+#include "chrome/browser/views/tabs/hwnd_photobooth.h"
+#include "chrome/browser/views/tabs/tab_renderer.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);
+}
+