contents_container.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/frame/contents_container.h" 6 7#include "base/logging.h" 8#include "third_party/skia/include/core/SkColor.h" 9#include "ui/base/animation/slide_animation.h" 10#include "views/background.h" 11#include "views/widget/root_view.h" 12#include "views/widget/widget.h" 13 14// Min/max opacity of the overlay. 15static const int kMinOpacity = 0; 16static const int kMaxOpacity = 192; 17 18// View used to track when the overlay widget is destroyed. If the 19// ContentsContainer is still valid when the destructor is invoked this invokes 20// |OverlayViewDestroyed| on the ContentsContainer. 21class ContentsContainer::OverlayContentView : public views::View { 22 public: 23 explicit OverlayContentView(ContentsContainer* container) 24 : container_(container) { 25 } 26 ~OverlayContentView() { 27 if (container_) 28 container_->OverlayViewDestroyed(); 29 } 30 31 void Detach() { 32 container_ = NULL; 33 } 34 35 private: 36 ContentsContainer* container_; 37 38 DISALLOW_COPY_AND_ASSIGN(OverlayContentView); 39}; 40 41ContentsContainer::ContentsContainer(views::View* active) 42 : active_(active), 43 preview_(NULL), 44 preview_tab_contents_(NULL), 45 active_overlay_(NULL), 46 overlay_view_(NULL), 47 active_top_margin_(0) { 48 AddChildView(active_); 49} 50 51ContentsContainer::~ContentsContainer() { 52 // We don't need to explicitly delete active_overlay_ as it'll be deleted by 53 // virtue of being a child window. 54 if (overlay_view_) 55 overlay_view_->Detach(); 56} 57 58void ContentsContainer::MakePreviewContentsActiveContents() { 59 RemoveFade(); 60 61 active_ = preview_; 62 preview_ = NULL; 63 Layout(); 64} 65 66void ContentsContainer::SetPreview(views::View* preview, 67 TabContents* preview_tab_contents) { 68 if (preview == preview_) 69 return; 70 71 if (preview_) 72 RemoveChildView(preview_); 73 preview_ = preview; 74 preview_tab_contents_ = preview_tab_contents; 75 if (preview_) 76 AddChildView(preview_); 77 78 Layout(); 79} 80 81void ContentsContainer::SetActiveTopMargin(int margin) { 82 if (active_top_margin_ == margin) 83 return; 84 85 active_top_margin_ = margin; 86 // Make sure we layout next time around. We need this in case our bounds 87 // haven't changed. 88 InvalidateLayout(); 89} 90 91gfx::Rect ContentsContainer::GetPreviewBounds() { 92 gfx::Point screen_loc; 93 ConvertPointToScreen(this, &screen_loc); 94 return gfx::Rect(screen_loc, size()); 95} 96 97void ContentsContainer::FadeActiveContents() { 98 if (active_overlay_ || !ui::Animation::ShouldRenderRichAnimation()) 99 return; 100 101#if !defined(OS_WIN) 102 // TODO: fix this. I'm disabling as z-order isn't right on linux so that 103 // overlay ends up obscuring the omnibox. 104 return; 105#endif 106 107 overlay_animation_.reset(new ui::SlideAnimation(this)); 108 overlay_animation_->SetDuration(300); 109 overlay_animation_->SetSlideDuration(300); 110 overlay_animation_->Show(); 111 112 CreateOverlay(kMinOpacity); 113} 114 115void ContentsContainer::ShowFade() { 116 if (active_overlay_ || !ui::Animation::ShouldRenderRichAnimation()) 117 return; 118 119 CreateOverlay(kMaxOpacity); 120} 121 122void ContentsContainer::RemoveFade() { 123 overlay_animation_.reset(); 124 if (active_overlay_) { 125 overlay_view_->Detach(); 126 overlay_view_ = NULL; 127 active_overlay_->Close(); 128 active_overlay_ = NULL; 129 } 130} 131 132void ContentsContainer::AnimationProgressed(const ui::Animation* animation) { 133 active_overlay_->SetOpacity( 134 ui::Tween::ValueBetween(animation->GetCurrentValue(), kMinOpacity, 135 kMaxOpacity)); 136 active_overlay_->GetRootView()->SchedulePaint(); 137} 138 139void ContentsContainer::Layout() { 140 // The active view always gets the full bounds. 141 active_->SetBounds(0, active_top_margin_, width(), 142 std::max(0, height() - active_top_margin_)); 143 144 if (preview_) 145 preview_->SetBounds(0, 0, width(), height()); 146 147 // Need to invoke views::View in case any views whose bounds didn't change 148 // still need a layout. 149 views::View::Layout(); 150} 151 152void ContentsContainer::CreateOverlay(int initial_opacity) { 153 DCHECK(!active_overlay_); 154 active_overlay_ = views::Widget::CreatePopupWidget(views::Widget::Transparent, 155 views::Widget::NotAcceptEvents, 156 views::Widget::DeleteOnDestroy, 157 views::Widget::MirrorOriginInRTL); 158 active_overlay_->SetOpacity(initial_opacity); 159 gfx::Point screen_origin; 160 views::View::ConvertPointToScreen(active_, &screen_origin); 161 gfx::Rect overlay_bounds(screen_origin, active_->size()); 162 active_overlay_->Init(active_->GetWidget()->GetNativeView(), overlay_bounds); 163 overlay_view_ = new OverlayContentView(this); 164 overlay_view_->set_background( 165 views::Background::CreateSolidBackground(SK_ColorWHITE)); 166 active_overlay_->SetContentsView(overlay_view_); 167 active_overlay_->Show(); 168 active_overlay_->MoveAbove(active_->GetWidget()); 169} 170 171void ContentsContainer::OverlayViewDestroyed() { 172 active_overlay_ = NULL; 173 overlay_view_ = NULL; 174} 175