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