Fixing build: GetViewContainer changed name from under me. :)
[chromium-blink-merge.git] / chrome / browser / views / download_shelf_view.cc
blob70b46346b464399c1423f8eb475c4bf3eba1dcc4
1 // Copyright (c) 2006-2008 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.
5 #include "chrome/browser/views/download_shelf_view.h"
7 #include <algorithm>
9 #include "chrome/app/theme/theme_resources.h"
10 #include "chrome/browser/browser.h"
11 #include "chrome/browser/download/download_item_model.h"
12 #include "chrome/browser/download/download_manager.h"
13 #include "chrome/browser/navigation_entry.h"
14 #include "chrome/browser/tab_contents.h"
15 #include "chrome/browser/views/download_item_view.h"
16 #include "chrome/browser/views/download_tab_view.h"
17 #include "chrome/common/gfx/chrome_canvas.h"
18 #include "chrome/common/l10n_util.h"
19 #include "base/logging.h"
20 #include "chrome/common/resource_bundle.h"
21 #include "chrome/views/background.h"
22 #include "chrome/views/button.h"
23 #include "chrome/views/image_view.h"
25 #include "generated_resources.h"
27 // Max number of download views we'll contain. Any time a view is added and
28 // we already have this many download views, one is removed.
29 static const int kMaxDownloadViews = 15;
31 // Padding from left edge and first download view.
32 static const int kLeftPadding = 2;
34 // Padding from right edge and close button/show downloads link.
35 static const int kRightPadding = 10;
37 // Padding between the show all link and close button.
38 static const int kCloseAndLinkPadding = 14;
40 // Padding between the download views.
41 static const int kDownloadPadding = 10;
43 // Padding between the top/bottom and the content.
44 static const int kTopBottomPadding = 2;
46 // Padding between the icon and 'show all downloads' link
47 static const int kDownloadsTitlePadding = 4;
49 // Default background color for the shelf.
50 static const SkColor kBackgroundColor = SkColorSetRGB(230, 237, 244);
52 // Border color.
53 static const SkColor kBorderColor = SkColorSetRGB(214, 214, 214);
55 // New download item animation speed in milliseconds.
56 static const int kNewItemAnimationDurationMs = 800;
58 // Shelf show/hide speed.
59 static const int kShelfAnimationDurationMs = 120;
61 namespace {
63 // Sets size->width() to view's preferred width + size->width().s
64 // Sets size->height() to the max of the view's preferred height and
65 // size->height();
66 void AdjustSize(ChromeViews::View* view, gfx::Size* size) {
67 gfx::Size view_preferred = view->GetPreferredSize();
68 size->Enlarge(view_preferred.width(), 0);
69 size->set_height(std::max(view_preferred.height(), size->height()));
72 int CenterPosition(int size, int target_size) {
73 return std::max((target_size - size) / 2, kTopBottomPadding);
76 } // namespace
78 DownloadShelfView::DownloadShelfView(TabContents* tab_contents)
79 : tab_contents_(tab_contents) {
80 Init();
83 void DownloadShelfView::Init() {
84 ResourceBundle &rb = ResourceBundle::GetSharedInstance();
85 arrow_image_ = new ChromeViews::ImageView();
86 arrow_image_->SetImage(rb.GetBitmapNamed(IDR_DOWNLOADS_FAVICON));
87 AddChildView(arrow_image_);
89 show_all_view_ =
90 new ChromeViews::Link(l10n_util::GetString(IDS_SHOW_ALL_DOWNLOADS));
91 show_all_view_->SetController(this);
92 AddChildView(show_all_view_);
94 close_button_ = new ChromeViews::Button();
95 close_button_->SetImage(ChromeViews::Button::BS_NORMAL,
96 rb.GetBitmapNamed(IDR_CLOSE_BAR));
97 close_button_->SetImage(ChromeViews::Button::BS_HOT,
98 rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
99 close_button_->SetImage(ChromeViews::Button::BS_PUSHED,
100 rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
101 close_button_->SetListener(this, 0);
102 AddChildView(close_button_);
103 SetBackground(
104 ChromeViews::Background::CreateSolidBackground(kBackgroundColor));
106 new_item_animation_.reset(new SlideAnimation(this));
107 new_item_animation_->SetSlideDuration(kNewItemAnimationDurationMs);
109 shelf_animation_.reset(new SlideAnimation(this));
110 shelf_animation_->SetSlideDuration(kShelfAnimationDurationMs);
111 shelf_animation_->Show();
114 void DownloadShelfView::AddDownloadView(View* view) {
115 DCHECK(view);
116 download_views_.push_back(view);
117 AddChildView(view);
118 if (download_views_.size() > kMaxDownloadViews)
119 RemoveDownloadView(*download_views_.begin());
121 new_item_animation_->Reset();
122 new_item_animation_->Show();
125 void DownloadShelfView::ChangeTabContents(TabContents* old_contents,
126 TabContents* new_contents) {
127 DCHECK(old_contents == tab_contents_);
128 tab_contents_ = new_contents;
131 void DownloadShelfView::AddDownload(DownloadItem* download) {
132 shelf_animation_->Show();
134 DownloadItemView* view = new DownloadItemView(
135 download, this, new DownloadItemModel(download));
136 AddDownloadView(view);
139 void DownloadShelfView::RemoveDownloadView(View* view) {
140 DCHECK(view);
141 std::vector<View*>::iterator i =
142 find(download_views_.begin(), download_views_.end(), view);
143 DCHECK(i != download_views_.end());
144 download_views_.erase(i);
145 RemoveChildView(view);
146 delete view;
147 if (download_views_.empty())
148 tab_contents_->SetDownloadShelfVisible(false);
149 Layout();
150 SchedulePaint();
153 void DownloadShelfView::Paint(ChromeCanvas* canvas) {
154 PaintBackground(canvas);
155 PaintBorder(canvas);
158 void DownloadShelfView::PaintBorder(ChromeCanvas* canvas) {
159 canvas->FillRectInt(kBorderColor, 0, 0, width(), 1);
162 gfx::Size DownloadShelfView::GetPreferredSize() {
163 gfx::Size prefsize(kRightPadding + kLeftPadding + kCloseAndLinkPadding, 0);
164 AdjustSize(close_button_, &prefsize);
165 AdjustSize(show_all_view_, &prefsize);
166 // Add one download view to the preferred size.
167 if (download_views_.size() > 0) {
168 AdjustSize(*download_views_.begin(), &prefsize);
169 prefsize.Enlarge(kDownloadPadding, 0);
171 prefsize.Enlarge(0, kTopBottomPadding + kTopBottomPadding);
172 if (shelf_animation_->IsAnimating()) {
173 prefsize.set_height(static_cast<int>(
174 static_cast<double>(prefsize.height()) *
175 shelf_animation_->GetCurrentValue()));
177 return prefsize;
180 void DownloadShelfView::AnimationProgressed(const Animation *animation) {
181 if (animation == new_item_animation_.get()) {
182 Layout();
183 SchedulePaint();
184 } else if (animation == shelf_animation_.get()) {
185 // Force a re-layout of the parent, which will call back into
186 // GetPreferredSize, where we will do our animation. In the case where the
187 // animation is hiding, we do a full resize - the fast resizing would
188 // otherwise leave blank white areas where the shelf was and where the
189 // user's eye is. Thankfully bottom-resizing is a lot faster than
190 // top-resizing.
191 tab_contents_->ToolbarSizeChanged(shelf_animation_->IsShowing());
195 void DownloadShelfView::AnimationEnded(const Animation *animation) {
196 if (animation == shelf_animation_.get()) {
197 tab_contents_->SetDownloadShelfVisible(shelf_animation_->IsShowing());
201 void DownloadShelfView::Layout() {
202 // When the download shelf is not visible it is not parented to anything,
203 // which means it is not safe to lay out the controls, so we return early.
204 // Otherwise, we can have problems when for example the user switches to
205 // another tab (that doesn't have a download shelf) _before_ the download
206 // has started and we'll crash when calling SetVisible() below because
207 // the NativeControlContainer ctor tries to use the Container.
208 if (!GetContainer())
209 return;
211 gfx::Size image_size = arrow_image_->GetPreferredSize();
212 gfx::Size close_button_size = close_button_->GetPreferredSize();
213 gfx::Size show_all_size = show_all_view_->GetPreferredSize();
214 int max_download_x =
215 std::max<int>(0, width() - kRightPadding - close_button_size.width() -
216 kCloseAndLinkPadding - show_all_size.width() -
217 image_size.width() - kDownloadPadding);
218 int next_x = max_download_x + kDownloadPadding;
219 // Align vertically with show_all_view_.
220 arrow_image_->SetBounds(next_x,
221 CenterPosition(show_all_size.height(), height()),
222 image_size.width(), image_size.height());
223 next_x += image_size.width() + kDownloadsTitlePadding;
224 show_all_view_->SetBounds(next_x,
225 CenterPosition(show_all_size.height(), height()),
226 show_all_size.width(),
227 show_all_size.height());
228 next_x += show_all_size.width() + kCloseAndLinkPadding;
229 close_button_->SetBounds(next_x,
230 CenterPosition(close_button_size.height(), height()),
231 close_button_size.width(),
232 close_button_size.height());
234 next_x = kLeftPadding;
235 std::vector<View*>::reverse_iterator ri;
236 for (ri = download_views_.rbegin(); ri != download_views_.rend(); ++ri) {
237 gfx::Size view_size = (*ri)->GetPreferredSize();
239 int x = next_x;
241 // Figure out width of item.
242 int item_width = view_size.width();
243 if (new_item_animation_->IsAnimating() && ri == download_views_.rbegin()) {
244 item_width = static_cast<int>(static_cast<double>(view_size.width()) *
245 new_item_animation_->GetCurrentValue());
248 next_x += (item_width + kDownloadPadding);
250 // Make sure our item can be contained within the shelf.
251 if (next_x < max_download_x) {
252 (*ri)->SetVisible(true);
253 (*ri)->SetBounds(x, CenterPosition(view_size.height(), height()),
254 item_width, view_size.height());
255 } else {
256 (*ri)->SetVisible(false);
261 // Open the download page.
262 void DownloadShelfView::LinkActivated(ChromeViews::Link* source,
263 int event_flags) {
264 int index;
265 NavigationController* controller = tab_contents_->controller();
266 Browser* browser = Browser::GetBrowserForController(controller, &index);
267 DCHECK(browser);
268 browser->ShowNativeUI(DownloadTabUI::GetURL());
271 void DownloadShelfView::ButtonPressed(ChromeViews::BaseButton* button) {
272 shelf_animation_->Hide();