Home | History | Annotate | Download | only in tray
      1 // Copyright (c) 2012 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 "ash/system/tray/tray_details_view.h"
      6 
      7 #include "ash/system/tray/fixed_sized_scroll_view.h"
      8 #include "ash/system/tray/system_tray_item.h"
      9 #include "ash/system/tray/tray_constants.h"
     10 #include "ui/gfx/canvas.h"
     11 #include "ui/views/background.h"
     12 #include "ui/views/controls/scroll_view.h"
     13 #include "ui/views/layout/box_layout.h"
     14 
     15 namespace ash {
     16 namespace internal {
     17 
     18 class ScrollSeparator : public views::View {
     19  public:
     20   ScrollSeparator() {}
     21 
     22   virtual ~ScrollSeparator() {}
     23 
     24  private:
     25   // Overriden from views::View.
     26   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
     27     canvas->FillRect(gfx::Rect(0, height() / 2, width(), 1), kBorderLightColor);
     28   }
     29   virtual gfx::Size GetPreferredSize() OVERRIDE {
     30     return gfx::Size(1, kTrayPopupScrollSeparatorHeight);
     31   }
     32 
     33   DISALLOW_COPY_AND_ASSIGN(ScrollSeparator);
     34 };
     35 
     36 class ScrollBorder : public views::Border {
     37  public:
     38   ScrollBorder() {}
     39   virtual ~ScrollBorder() {}
     40 
     41   void set_visible(bool visible) { visible_ = visible; }
     42 
     43  private:
     44   // Overridden from views::Border.
     45   virtual void Paint(const views::View& view, gfx::Canvas* canvas) OVERRIDE {
     46     if (!visible_)
     47       return;
     48     canvas->FillRect(gfx::Rect(0, view.height() - 1, view.width(), 1),
     49                      kBorderLightColor);
     50   }
     51 
     52   virtual gfx::Insets GetInsets() const OVERRIDE {
     53     return gfx::Insets(0, 0, 1, 0);
     54   }
     55 
     56   bool visible_;
     57 
     58   DISALLOW_COPY_AND_ASSIGN(ScrollBorder);
     59 };
     60 
     61 TrayDetailsView::TrayDetailsView(SystemTrayItem* owner)
     62     : owner_(owner),
     63       footer_(NULL),
     64       scroller_(NULL),
     65       scroll_content_(NULL),
     66       scroll_border_(NULL) {
     67   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
     68       0, 0, 0));
     69   set_background(views::Background::CreateSolidBackground(kBackgroundColor));
     70 }
     71 
     72 TrayDetailsView::~TrayDetailsView() {
     73 }
     74 
     75 void TrayDetailsView::CreateSpecialRow(int string_id,
     76                                        ViewClickListener* listener) {
     77   DCHECK(!footer_);
     78   footer_ = new SpecialPopupRow();
     79   footer_->SetTextLabel(string_id, listener);
     80   AddChildViewAt(footer_, child_count());
     81 }
     82 
     83 void TrayDetailsView::CreateScrollableList() {
     84   DCHECK(!scroller_);
     85   scroll_content_ = new views::View;
     86   scroll_content_->SetLayoutManager(new views::BoxLayout(
     87       views::BoxLayout::kVertical, 0, 0, 1));
     88   scroller_ = new FixedSizedScrollView;
     89   scroller_->SetContentsView(scroll_content_);
     90 
     91   // Note: |scroller_| takes ownership of |scroll_border_|.
     92   scroll_border_ = new ScrollBorder;
     93   scroller_->set_border(scroll_border_);
     94 
     95   AddChildView(scroller_);
     96 }
     97 
     98 void TrayDetailsView::AddScrollSeparator() {
     99   DCHECK(scroll_content_);
    100   // Do not draw the separator if it is the very first item
    101   // in the scrollable list.
    102   if (scroll_content_->has_children())
    103     scroll_content_->AddChildView(new ScrollSeparator);
    104 }
    105 
    106 void TrayDetailsView::Reset() {
    107   RemoveAllChildViews(true);
    108   footer_ = NULL;
    109   scroller_ = NULL;
    110   scroll_content_ = NULL;
    111 }
    112 
    113 void TrayDetailsView::Layout() {
    114   if (!scroller_ || !footer_ || bounds().IsEmpty()) {
    115     views::View::Layout();
    116     return;
    117   }
    118 
    119   scroller_->set_fixed_size(gfx::Size());
    120   gfx::Size size = GetPreferredSize();
    121 
    122   // Set the scroller to fill the space above the bottom row, so that the
    123   // bottom row of the detailed view will always stay just above the footer.
    124   gfx::Size scroller_size = scroll_content_->GetPreferredSize();
    125   scroller_->set_fixed_size(gfx::Size(
    126       width() + scroller_->GetScrollBarWidth(),
    127       scroller_size.height() - (size.height() - height())));
    128 
    129   views::View::Layout();
    130   // Always make sure the footer element is bottom aligned.
    131   gfx::Rect fbounds = footer_->bounds();
    132   fbounds.set_y(height() - footer_->height());
    133   footer_->SetBoundsRect(fbounds);
    134 }
    135 
    136 void TrayDetailsView::OnPaintBorder(gfx::Canvas* canvas) {
    137   if (scroll_border_) {
    138     int index = GetIndexOf(scroller_);
    139     if (index < child_count() - 1 && child_at(index + 1) != footer_)
    140       scroll_border_->set_visible(true);
    141     else
    142       scroll_border_->set_visible(false);
    143   }
    144 
    145   views::View::OnPaintBorder(canvas);
    146 }
    147 
    148 }  // namespace internal
    149 }  // namespace ash
    150