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