1// Copyright (c) 2011 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// A ChromeView that implements one download on the Download shelf.
6// Each DownloadItemView contains an application icon, a text label
7// indicating the download's file name, a text label indicating the
8// download's status (such as the number of bytes downloaded so far)
9// and a button for canceling an in progress download, or opening
10// the completed download.
11//
12// The DownloadItemView lives in the Browser, and has a corresponding
13// DownloadController that receives / writes data which lives in the
14// Renderer.
15
16#ifndef CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__
17#define CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__
18#pragma once
19
20#include <string>
21
22#include "base/basictypes.h"
23#include "base/memory/scoped_ptr.h"
24#include "base/time.h"
25#include "base/timer.h"
26#include "chrome/browser/download/download_item.h"
27#include "chrome/browser/download/download_manager.h"
28#include "chrome/browser/icon_manager.h"
29#include "content/browser/cancelable_request.h"
30#include "ui/base/animation/animation_delegate.h"
31#include "ui/gfx/font.h"
32#include "views/controls/button/button.h"
33#include "views/events/event.h"
34#include "views/view.h"
35
36class BaseDownloadItemModel;
37class DownloadShelfView;
38class SkBitmap;
39class DownloadShelfContextMenuWin;
40
41namespace gfx {
42class Image;
43}
44
45namespace ui {
46class SlideAnimation;
47}
48
49namespace views {
50class Label;
51class NativeButton;
52}
53
54class DownloadItemView : public views::ButtonListener,
55                         public views::View,
56                         public DownloadItem::Observer,
57                         public ui::AnimationDelegate {
58 public:
59  DownloadItemView(DownloadItem* download,
60                   DownloadShelfView* parent,
61                   BaseDownloadItemModel* model);
62  virtual ~DownloadItemView();
63
64  // Timer callback for handling animations
65  void UpdateDownloadProgress();
66  void StartDownloadProgress();
67  void StopDownloadProgress();
68
69  // IconManager::Client interface.
70  void OnExtractIconComplete(IconManager::Handle handle, gfx::Image* icon);
71
72  // Returns the DownloadItem model object belonging to this item.
73  DownloadItem* download() const { return download_; }
74
75  // DownloadObserver method
76  virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
77  virtual void OnDownloadOpened(DownloadItem* download) OVERRIDE;
78
79  // Overridden from views::View:
80  virtual void Layout() OVERRIDE;
81  virtual gfx::Size GetPreferredSize() OVERRIDE;
82  virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE;
83  virtual bool OnMouseDragged(const views::MouseEvent& event) OVERRIDE;
84  virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE;
85  virtual void OnMouseCaptureLost() OVERRIDE;
86  virtual void OnMouseMoved(const views::MouseEvent& event) OVERRIDE;
87  virtual void OnMouseExited(const views::MouseEvent& event) OVERRIDE;
88  virtual bool OnKeyPressed(const views::KeyEvent& event) OVERRIDE;
89  virtual bool GetTooltipText(const gfx::Point& p,
90                              std::wstring* tooltip) OVERRIDE;
91  virtual void ShowContextMenu(const gfx::Point& p,
92                               bool is_mouse_gesture) OVERRIDE;
93  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
94
95  // ButtonListener implementation.
96  virtual void ButtonPressed(views::Button* sender,
97                             const views::Event& event) OVERRIDE;
98
99  // ui::AnimationDelegate implementation.
100  virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
101
102 protected:
103  // Overridden from views::View:
104  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
105
106 private:
107  enum State {
108    NORMAL = 0,
109    HOT,
110    PUSHED,
111    DANGEROUS
112  };
113
114  // The image set associated with the part containing the icon and text.
115  struct BodyImageSet {
116    SkBitmap* top_left;
117    SkBitmap* left;
118    SkBitmap* bottom_left;
119    SkBitmap* top;
120    SkBitmap* center;
121    SkBitmap* bottom;
122    SkBitmap* top_right;
123    SkBitmap* right;
124    SkBitmap* bottom_right;
125  };
126
127  // The image set associated with the drop-down button on the right.
128  struct DropDownImageSet {
129    SkBitmap* top;
130    SkBitmap* center;
131    SkBitmap* bottom;
132  };
133
134  void OpenDownload();
135
136  void LoadIcon();
137
138  // Convenience method to paint the 3 vertical bitmaps (bottom, middle, top)
139  // that form the background.
140  void PaintBitmaps(gfx::Canvas* canvas,
141                    const SkBitmap* top_bitmap,
142                    const SkBitmap* center_bitmap,
143                    const SkBitmap* bottom_bitmap,
144                    int x,
145                    int y,
146                    int height,
147                    int width);
148
149  // Sets the state and triggers a repaint.
150  void SetState(State body_state, State drop_down_state);
151
152  // Whether we are in the dangerous mode.
153  bool IsDangerousMode() { return body_state_ == DANGEROUS; }
154
155  // Reverts from dangerous mode to normal download mode.
156  void ClearDangerousMode();
157
158  // Sets |size| with the size of the Save and Discard buttons (they have the
159  // same size).
160  gfx::Size GetButtonSize();
161
162  // Sizes the dangerous download label to a minimum width available using 2
163  // lines.  The size is computed only the first time this method is invoked
164  // and simply returned on subsequent calls.
165  void SizeLabelToMinWidth();
166
167  // Reenables the item after it has been disabled when a user clicked it to
168  // open the downloaded file.
169  void Reenable();
170
171  // Given |x|, returns whether |x| is within the x coordinate range of
172  // the drop-down button or not.
173  bool InDropDownButtonXCoordinateRange(int x);
174
175  // Update the accessible name to reflect the current state of the control,
176  // so that screenreaders can access the filename, status text, and
177  // dangerous download warning message (if any).
178  void UpdateAccessibleName();
179
180  // The different images used for the background.
181  BodyImageSet normal_body_image_set_;
182  BodyImageSet hot_body_image_set_;
183  BodyImageSet pushed_body_image_set_;
184  BodyImageSet dangerous_mode_body_image_set_;
185  DropDownImageSet normal_drop_down_image_set_;
186  DropDownImageSet hot_drop_down_image_set_;
187  DropDownImageSet pushed_drop_down_image_set_;
188
189  // The warning icon showns for dangerous downloads.
190  const SkBitmap* warning_icon_;
191
192  // The model we query for display information
193  DownloadItem* download_;
194
195  // Our parent view that owns us.
196  DownloadShelfView* parent_;
197
198  // Elements of our particular download
199  std::wstring status_text_;
200  bool show_status_text_;
201
202  // The font used to print the file name and status.
203  gfx::Font font_;
204
205  // The tooltip.
206  std::wstring tooltip_text_;
207
208  // The current state (normal, hot or pushed) of the body and drop-down.
209  State body_state_;
210  State drop_down_state_;
211
212  // In degrees, for downloads with no known total size.
213  int progress_angle_;
214
215  // The left and right x coordinates of the drop-down button.
216  int drop_down_x_left_;
217  int drop_down_x_right_;
218
219  // Used when we are showing the menu to show the drop-down as pressed.
220  bool drop_down_pressed_;
221
222  // The height of the box formed by the background images and its labels.
223  int box_height_;
224
225  // The y coordinate of the box formed by the background images and its labels.
226  int box_y_;
227
228  // Whether we are dragging the download button.
229  bool dragging_;
230
231  // Whether we are tracking a possible drag.
232  bool starting_drag_;
233
234  // Position that a possible drag started at.
235  gfx::Point drag_start_point_;
236
237  // For canceling an in progress icon request.
238  CancelableRequestConsumerT<int, 0> icon_consumer_;
239
240  // A model class to control the status text we display and the cancel
241  // behavior.
242  // This class owns the pointer.
243  scoped_ptr<BaseDownloadItemModel> model_;
244
245  // Hover animations for our body and drop buttons.
246  scoped_ptr<ui::SlideAnimation> body_hover_animation_;
247  scoped_ptr<ui::SlideAnimation> drop_hover_animation_;
248
249  // Animation for download complete.
250  scoped_ptr<ui::SlideAnimation> complete_animation_;
251
252  // Progress animation
253  base::RepeatingTimer<DownloadItemView> progress_timer_;
254
255  // Dangerous mode buttons.
256  views::NativeButton* save_button_;
257  views::NativeButton* discard_button_;
258
259  // Dangerous mode label.
260  views::Label* dangerous_download_label_;
261
262  // Whether the dangerous mode label has been sized yet.
263  bool dangerous_download_label_sized_;
264
265  // The size of the buttons.  Cached so animation works when hidden.
266  gfx::Size cached_button_size_;
267
268  // Whether we are currently disabled as part of opening the downloaded file.
269  bool disabled_while_opening_;
270
271  // The time at which this view was created.
272  base::Time creation_time_;
273
274  // Method factory used to delay reenabling of the item when opening the
275  // downloaded file.
276  ScopedRunnableMethodFactory<DownloadItemView> reenable_method_factory_;
277
278  // The currently running download context menu.
279  scoped_ptr<DownloadShelfContextMenuWin> context_menu_;
280
281  // If non-NULL, set to true when this object is deleted.
282  // (Used when showing the context menu as it runs an inner message loop that
283  // might delete us).
284  bool* deleted_;
285
286  // The name of this view as reported to assistive technology.
287  string16 accessible_name_;
288
289  DISALLOW_COPY_AND_ASSIGN(DownloadItemView);
290};
291
292#endif  // CHROME_BROWSER_UI_VIEWS_DOWNLOAD_DOWNLOAD_ITEM_VIEW_H__
293