Home | History | Annotate | Download | only in frame
      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.
     15 static const int kMinOpacity = 0;
     16 static 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.
     21 class 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 
     41 ContentsContainer::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 
     51 ContentsContainer::~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 
     58 void ContentsContainer::MakePreviewContentsActiveContents() {
     59   DCHECK(preview_);
     60   RemoveFade();
     61 
     62   active_ = preview_;
     63   preview_ = NULL;
     64   Layout();
     65 }
     66 
     67 void ContentsContainer::SetPreview(views::View* preview,
     68                                    TabContents* preview_tab_contents) {
     69   if (preview == preview_)
     70     return;
     71 
     72   if (preview_)
     73     RemoveChildView(preview_);
     74   preview_ = preview;
     75   preview_tab_contents_ = preview_tab_contents;
     76   if (preview_)
     77     AddChildView(preview_);
     78 
     79   Layout();
     80 }
     81 
     82 void ContentsContainer::SetActiveTopMargin(int margin) {
     83   if (active_top_margin_ == margin)
     84     return;
     85 
     86   active_top_margin_ = margin;
     87   // Make sure we layout next time around. We need this in case our bounds
     88   // haven't changed.
     89   InvalidateLayout();
     90 }
     91 
     92 gfx::Rect ContentsContainer::GetPreviewBounds() {
     93   gfx::Point screen_loc;
     94   ConvertPointToScreen(this, &screen_loc);
     95   return gfx::Rect(screen_loc, size());
     96 }
     97 
     98 void ContentsContainer::FadeActiveContents() {
     99   if (active_overlay_ || !ui::Animation::ShouldRenderRichAnimation())
    100     return;
    101 
    102 #if !defined(OS_WIN)
    103   // TODO: fix this. I'm disabling as z-order isn't right on linux so that
    104   // overlay ends up obscuring the omnibox.
    105   return;
    106 #endif
    107 
    108   overlay_animation_.reset(new ui::SlideAnimation(this));
    109   overlay_animation_->SetDuration(300);
    110   overlay_animation_->SetSlideDuration(300);
    111   overlay_animation_->Show();
    112 
    113   CreateOverlay(kMinOpacity);
    114 }
    115 
    116 void ContentsContainer::ShowFade() {
    117   if (active_overlay_ || !ui::Animation::ShouldRenderRichAnimation())
    118     return;
    119 
    120   CreateOverlay(kMaxOpacity);
    121 }
    122 
    123 void ContentsContainer::RemoveFade() {
    124   overlay_animation_.reset();
    125   if (active_overlay_) {
    126     overlay_view_->Detach();
    127     overlay_view_ = NULL;
    128     active_overlay_->Close();
    129     active_overlay_ = NULL;
    130   }
    131 }
    132 
    133 void ContentsContainer::AnimationProgressed(const ui::Animation* animation) {
    134   active_overlay_->SetOpacity(
    135       ui::Tween::ValueBetween(animation->GetCurrentValue(), kMinOpacity,
    136                               kMaxOpacity));
    137   active_overlay_->GetRootView()->SchedulePaint();
    138 }
    139 
    140 void ContentsContainer::Layout() {
    141   // The active view always gets the full bounds.
    142   active_->SetBounds(0, active_top_margin_, width(),
    143                      std::max(0, height() - active_top_margin_));
    144 
    145   if (preview_)
    146     preview_->SetBounds(0, 0, width(), height());
    147 
    148   // Need to invoke views::View in case any views whose bounds didn't change
    149   // still need a layout.
    150   views::View::Layout();
    151 }
    152 
    153 void ContentsContainer::CreateOverlay(int initial_opacity) {
    154   DCHECK(!active_overlay_);
    155   views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP);
    156   params.transparent = true;
    157   params.accept_events = false;
    158   active_overlay_ = views::Widget::CreateWidget(params);
    159   active_overlay_->SetOpacity(initial_opacity);
    160   gfx::Point screen_origin;
    161   views::View::ConvertPointToScreen(active_, &screen_origin);
    162   gfx::Rect overlay_bounds(screen_origin, active_->size());
    163   active_overlay_->Init(active_->GetWidget()->GetNativeView(), overlay_bounds);
    164   overlay_view_ = new OverlayContentView(this);
    165   overlay_view_->set_background(
    166       views::Background::CreateSolidBackground(SK_ColorWHITE));
    167   active_overlay_->SetContentsView(overlay_view_);
    168   active_overlay_->Show();
    169   active_overlay_->MoveAboveWidget(active_->GetWidget());
    170 }
    171 
    172 void ContentsContainer::OverlayViewDestroyed() {
    173   active_overlay_ = NULL;
    174   overlay_view_ = NULL;
    175 }
    176