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#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SHELF_H_
6#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SHELF_H_
7
8#include "base/callback_forward.h"
9#include "base/memory/weak_ptr.h"
10#include "base/time/time.h"
11#include "build/build_config.h"
12
13class Browser;
14
15namespace gfx {
16class Canvas;
17class ImageSkia;
18class Rect;
19}
20
21namespace content {
22class DownloadItem;
23class DownloadManager;
24}
25
26// This is an abstract base class for platform specific download shelf
27// implementations.
28class DownloadShelf {
29 public:
30  // Reason for closing download shelf.
31  enum CloseReason {
32    // Closing the shelf automatically. E.g.: all remaining downloads in the
33    // shelf have been opened, last download in shelf was removed, or the
34    // browser is switching to full-screen mode.
35    AUTOMATIC,
36
37    // Closing shelf due to a user selection. E.g.: the user clicked on the
38    // 'close' button on the download shelf, or the shelf is being closed as a
39    // side-effect of the user opening the downloads page.
40    USER_ACTION
41  };
42
43  enum PaintDownloadProgressSize {
44    SMALL = 0,
45    BIG
46  };
47
48  // Download progress animations ----------------------------------------------
49
50  enum {
51    // Arc sweep angle for use with downloads of unknown size.
52    kUnknownAngleDegrees = 50,
53
54    // Rate of progress for use with downloads of unknown size.
55    kUnknownIncrementDegrees = 12,
56
57    // Start angle for downloads with known size (midnight position).
58    kStartAngleDegrees = -90,
59
60    // A the maximum number of degrees of a circle.
61    kMaxDegrees = 360,
62
63    // Progress animation timer period, in milliseconds.
64    kProgressRateMs = 150,
65
66    // XP and Vista must support icons of this size.
67    kSmallIconSize = 16,
68    kBigIconSize = 32,
69
70    kSmallProgressIconSize = 39,
71    kBigProgressIconSize = 52,
72
73    kSmallProgressIconOffset = (kSmallProgressIconSize - kSmallIconSize) / 2
74  };
75
76  // Type of the callback used on toolkit-views platforms for the |rtl_mirror|
77  // argument of the PaintDownload functions. It captures the View subclass
78  // within which the progress animation is drawn and is used to update the
79  // correct 'left' value for the given rectangle in RTL locales. This is used
80  // to mirror the position of the progress animation. The callback is
81  // guaranteed to be invoked before the paint function returns.
82  typedef base::Callback<void(gfx::Rect*)> BoundsAdjusterCallback;
83
84  DownloadShelf();
85  virtual ~DownloadShelf();
86
87  // Our progress halo around the icon.
88  // Load a language dependent height so that the dangerous download
89  // confirmation message doesn't overlap with the download link label.
90  static int GetBigProgressIconSize();
91
92  // The offset required to center the icon in the progress images.
93  static int GetBigProgressIconOffset();
94
95  // Paint the common download animation progress foreground and background,
96  // clipping the foreground to 'percent' full. If percent is -1, then we don't
97  // know the total size, so we just draw a rotating segment until we're done.
98  static void PaintCustomDownloadProgress(
99      gfx::Canvas* canvas,
100      const gfx::ImageSkia& background_image,
101      const gfx::ImageSkia& foreground_image,
102      int image_size,
103      const gfx::Rect& bounds,
104      int start_angle,
105      int percent_done);
106
107  static void PaintDownloadProgress(gfx::Canvas* canvas,
108                                    const BoundsAdjusterCallback& rtl_mirror,
109                                    int origin_x,
110                                    int origin_y,
111                                    int start_angle,
112                                    int percent,
113                                    PaintDownloadProgressSize size);
114
115  static void PaintDownloadComplete(gfx::Canvas* canvas,
116                                    const BoundsAdjusterCallback& rtl_mirror,
117                                    int origin_x,
118                                    int origin_y,
119                                    double animation_progress,
120                                    PaintDownloadProgressSize size);
121
122  static void PaintDownloadInterrupted(gfx::Canvas* canvas,
123                                       const BoundsAdjusterCallback& rtl_mirror,
124                                       int origin_x,
125                                       int origin_y,
126                                       double animation_progress,
127                                       PaintDownloadProgressSize size);
128
129  // A new download has started. Add it to our shelf and show the download
130  // started animation.
131  //
132  // Some downloads are removed from the shelf on completion (See
133  // DownloadItemModel::ShouldRemoveFromShelfWhenComplete()). These transient
134  // downloads are added to the shelf after a delay. If the download completes
135  // before the delay duration, it will not be added to the shelf at all.
136  void AddDownload(content::DownloadItem* download);
137
138  // The browser view needs to know when we are going away to properly return
139  // the resize corner size to WebKit so that we don't draw on top of it.
140  // This returns the showing state of our animation which is set to true at
141  // the beginning Show and false at the beginning of a Hide.
142  virtual bool IsShowing() const = 0;
143
144  // Returns whether the download shelf is showing the close animation.
145  virtual bool IsClosing() const = 0;
146
147  // Opens the shelf.
148  void Show();
149
150  // Closes the shelf.
151  void Close(CloseReason reason);
152
153  // Hides the shelf. This closes the shelf if it is currently showing.
154  void Hide();
155
156  // Unhides the shelf. This will cause the shelf to be opened if it was open
157  // when it was hidden, or was shown while it was hidden.
158  void Unhide();
159
160  virtual Browser* browser() const = 0;
161
162  // Returns whether the download shelf is hidden.
163  bool is_hidden() { return is_hidden_; }
164
165 protected:
166  virtual void DoAddDownload(content::DownloadItem* download) = 0;
167  virtual void DoShow() = 0;
168  virtual void DoClose(CloseReason reason) = 0;
169
170  // Time delay to wait before adding a transient download to the shelf.
171  // Protected virtual for testing.
172  virtual base::TimeDelta GetTransientDownloadShowDelay();
173
174  // Returns the DownloadManager associated with this DownloadShelf. All
175  // downloads that are shown on this shelf is expected to belong to this
176  // DownloadManager. Protected virtual for testing.
177  virtual content::DownloadManager* GetDownloadManager();
178
179 private:
180  // Show the download on the shelf immediately. Also displayes the download
181  // started animation if necessary.
182  void ShowDownload(content::DownloadItem* download);
183
184  // Similar to ShowDownload() but refers to the download using an ID. This
185  // download should belong to the DownloadManager returned by
186  // GetDownloadManager().
187  void ShowDownloadById(int32 download_id);
188
189  bool should_show_on_unhide_;
190  bool is_hidden_;
191  base::WeakPtrFactory<DownloadShelf> weak_ptr_factory_;
192};
193
194#endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_SHELF_H_
195