OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/views/download_item_view.h" | 5 #include "chrome/browser/views/download_item_view.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "app/gfx/canvas.h" | 9 #include "app/gfx/canvas.h" |
10 #include "app/gfx/text_elider.h" | 10 #include "app/gfx/text_elider.h" |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 | 65 |
66 // How long we keep the item disabled after the user clicked it to open the | 66 // How long we keep the item disabled after the user clicked it to open the |
67 // downloaded item. | 67 // downloaded item. |
68 static const int kDisabledOnOpenDuration = 3000; | 68 static const int kDisabledOnOpenDuration = 3000; |
69 | 69 |
70 // DownloadShelfContextMenuWin ------------------------------------------------- | 70 // DownloadShelfContextMenuWin ------------------------------------------------- |
71 | 71 |
72 class DownloadShelfContextMenuWin : public DownloadShelfContextMenu, | 72 class DownloadShelfContextMenuWin : public DownloadShelfContextMenu, |
73 public views::Menu::Delegate { | 73 public views::Menu::Delegate { |
74 public: | 74 public: |
75 DownloadShelfContextMenuWin(BaseDownloadItemModel* model, | 75 DownloadShelfContextMenuWin(BaseDownloadItemModel* model) |
76 gfx::NativeView window, | |
77 const gfx::Point& point) | |
78 : DownloadShelfContextMenu(model) { | 76 : DownloadShelfContextMenu(model) { |
79 DCHECK(model); | 77 DCHECK(model); |
| 78 } |
80 | 79 |
| 80 void Run(gfx::NativeView window, const gfx::Point& point) { |
81 // The menu's anchor point is determined based on the UI layout. | 81 // The menu's anchor point is determined based on the UI layout. |
82 views::Menu::AnchorPoint anchor_point; | 82 views::Menu::AnchorPoint anchor_point; |
83 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) | 83 if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) |
84 anchor_point = views::Menu::TOPRIGHT; | 84 anchor_point = views::Menu::TOPRIGHT; |
85 else | 85 else |
86 anchor_point = views::Menu::TOPLEFT; | 86 anchor_point = views::Menu::TOPLEFT; |
87 | 87 |
88 scoped_ptr<views::Menu> context_menu( | 88 scoped_ptr<views::Menu> context_menu( |
89 views::Menu::Create(this, anchor_point, window)); | 89 views::Menu::Create(this, anchor_point, window)); |
90 if (download_->state() == DownloadItem::COMPLETE) { | 90 if (download_->state() == DownloadItem::COMPLETE) { |
91 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", | 91 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", |
92 views::Menu::NORMAL); | 92 views::Menu::NORMAL); |
93 } else { | 93 } else { |
94 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", | 94 context_menu->AppendMenuItem(OPEN_WHEN_COMPLETE, L"", |
95 views::Menu::CHECKBOX); | 95 views::Menu::CHECKBOX); |
96 } | 96 } |
97 context_menu->AppendMenuItem(ALWAYS_OPEN_TYPE, L"", views::Menu::CHECKBOX); | 97 context_menu->AppendMenuItem(ALWAYS_OPEN_TYPE, L"", views::Menu::CHECKBOX); |
98 context_menu->AppendSeparator(); | 98 context_menu->AppendSeparator(); |
99 if (download_->state() == DownloadItem::IN_PROGRESS) | 99 if (download_->state() == DownloadItem::IN_PROGRESS) |
100 context_menu->AppendMenuItem(TOGGLE_PAUSE, L"", views::Menu::NORMAL); | 100 context_menu->AppendMenuItem(TOGGLE_PAUSE, L"", views::Menu::NORMAL); |
101 context_menu->AppendMenuItem(SHOW_IN_FOLDER, L"", views::Menu::NORMAL); | 101 context_menu->AppendMenuItem(SHOW_IN_FOLDER, L"", views::Menu::NORMAL); |
102 context_menu->AppendSeparator(); | 102 context_menu->AppendSeparator(); |
103 context_menu->AppendMenuItem(REMOVE_ITEM, L"", views::Menu::NORMAL); | 103 context_menu->AppendMenuItem(REMOVE_ITEM, L"", views::Menu::NORMAL); |
104 context_menu->AppendMenuItem(CANCEL, L"", views::Menu::NORMAL); | 104 context_menu->AppendMenuItem(CANCEL, L"", views::Menu::NORMAL); |
105 context_menu->RunMenuAt(point.x(), point.y()); | 105 context_menu->RunMenuAt(point.x(), point.y()); |
106 } | 106 } |
107 | 107 |
| 108 // This method runs when the caller has been deleted and we should not attempt |
| 109 // to access |download_|. |
| 110 void Stop() { |
| 111 download_ = NULL; |
| 112 model_ = NULL; |
| 113 } |
| 114 |
108 // Menu::Delegate implementation --------------------------------------------- | 115 // Menu::Delegate implementation --------------------------------------------- |
109 | 116 |
110 virtual bool IsItemChecked(int id) const { | 117 virtual bool IsItemChecked(int id) const { |
| 118 if (!download_) |
| 119 return false; |
111 return ItemIsChecked(id); | 120 return ItemIsChecked(id); |
112 } | 121 } |
113 | 122 |
114 virtual bool IsItemDefault(int id) const { | 123 virtual bool IsItemDefault(int id) const { |
| 124 if (!download_) |
| 125 return false; |
115 return ItemIsDefault(id); | 126 return ItemIsDefault(id); |
116 } | 127 } |
117 | 128 |
118 virtual std::wstring GetLabel(int id) const { | 129 virtual std::wstring GetLabel(int id) const { |
| 130 if (!download_) |
| 131 return std::wstring(); |
119 return GetItemLabel(id); | 132 return GetItemLabel(id); |
120 } | 133 } |
121 | 134 |
122 virtual bool SupportsCommand(int id) const { | 135 virtual bool SupportsCommand(int id) const { |
| 136 if (!download_) |
| 137 return false; |
123 return id > 0 && id < MENU_LAST; | 138 return id > 0 && id < MENU_LAST; |
124 } | 139 } |
125 | 140 |
126 virtual bool IsCommandEnabled(int id) const { | 141 virtual bool IsCommandEnabled(int id) const { |
| 142 if (!download_) |
| 143 return false; |
127 return IsItemCommandEnabled(id); | 144 return IsItemCommandEnabled(id); |
128 } | 145 } |
129 | 146 |
130 virtual void ExecuteCommand(int id) { | 147 virtual void ExecuteCommand(int id) { |
131 return ExecuteItemCommand(id); | 148 if (download_) |
| 149 ExecuteItemCommand(id); |
132 } | 150 } |
133 }; | 151 }; |
134 | 152 |
135 // DownloadItemView ------------------------------------------------------------ | 153 // DownloadItemView ------------------------------------------------------------ |
136 | 154 |
137 DownloadItemView::DownloadItemView(DownloadItem* download, | 155 DownloadItemView::DownloadItemView(DownloadItem* download, |
138 DownloadShelfView* parent, | 156 DownloadShelfView* parent, |
139 BaseDownloadItemModel* model) | 157 BaseDownloadItemModel* model) |
140 : warning_icon_(NULL), | 158 : warning_icon_(NULL), |
141 download_(download), | 159 download_(download), |
142 parent_(parent), | 160 parent_(parent), |
143 status_text_(l10n_util::GetString(IDS_DOWNLOAD_STATUS_STARTING)), | 161 status_text_(l10n_util::GetString(IDS_DOWNLOAD_STATUS_STARTING)), |
144 show_status_text_(true), | 162 show_status_text_(true), |
145 body_state_(NORMAL), | 163 body_state_(NORMAL), |
146 drop_down_state_(NORMAL), | 164 drop_down_state_(NORMAL), |
147 progress_angle_(download_util::kStartAngleDegrees), | 165 progress_angle_(download_util::kStartAngleDegrees), |
148 drop_down_pressed_(false), | 166 drop_down_pressed_(false), |
149 dragging_(false), | 167 dragging_(false), |
150 starting_drag_(false), | 168 starting_drag_(false), |
151 model_(model), | 169 model_(model), |
152 save_button_(NULL), | 170 save_button_(NULL), |
153 discard_button_(NULL), | 171 discard_button_(NULL), |
154 dangerous_download_label_(NULL), | 172 dangerous_download_label_(NULL), |
155 dangerous_download_label_sized_(false), | 173 dangerous_download_label_sized_(false), |
156 disabled_while_opening_(false), | 174 disabled_while_opening_(false), |
157 creation_time_(base::Time::Now()), | 175 creation_time_(base::Time::Now()), |
158 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)) { | 176 ALLOW_THIS_IN_INITIALIZER_LIST(reenable_method_factory_(this)), |
| 177 active_menu_(NULL) { |
159 DCHECK(download_); | 178 DCHECK(download_); |
160 download_->AddObserver(this); | 179 download_->AddObserver(this); |
161 | 180 |
162 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); | 181 ResourceBundle &rb = ResourceBundle::GetSharedInstance(); |
163 | 182 |
164 BodyImageSet normal_body_image_set = { | 183 BodyImageSet normal_body_image_set = { |
165 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), | 184 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_TOP), |
166 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), | 185 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_MIDDLE), |
167 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), | 186 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_LEFT_BOTTOM), |
168 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), | 187 rb.GetBitmapNamed(IDR_DOWNLOAD_BUTTON_CENTER_TOP), |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 views::Label::ALIGN_LEFT); | 332 views::Label::ALIGN_LEFT); |
314 AddChildView(dangerous_download_label_); | 333 AddChildView(dangerous_download_label_); |
315 SizeLabelToMinWidth(); | 334 SizeLabelToMinWidth(); |
316 } | 335 } |
317 | 336 |
318 // Set up our animation. | 337 // Set up our animation. |
319 StartDownloadProgress(); | 338 StartDownloadProgress(); |
320 } | 339 } |
321 | 340 |
322 DownloadItemView::~DownloadItemView() { | 341 DownloadItemView::~DownloadItemView() { |
| 342 if (active_menu_) { |
| 343 active_menu_->Stop(); |
| 344 active_menu_ = NULL; |
| 345 } |
323 icon_consumer_.CancelAllRequests(); | 346 icon_consumer_.CancelAllRequests(); |
324 StopDownloadProgress(); | 347 StopDownloadProgress(); |
325 download_->RemoveObserver(this); | 348 download_->RemoveObserver(this); |
326 } | 349 } |
327 | 350 |
328 // Progress animation handlers. | 351 // Progress animation handlers. |
329 | 352 |
330 void DownloadItemView::UpdateDownloadProgress() { | 353 void DownloadItemView::UpdateDownloadProgress() { |
331 progress_angle_ = (progress_angle_ + | 354 progress_angle_ = (progress_angle_ + |
332 download_util::kUnknownIncrementDegrees) % | 355 download_util::kUnknownIncrementDegrees) % |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
810 // The menu's position is different depending on the UI layout. | 833 // The menu's position is different depending on the UI layout. |
811 // DownloadShelfContextMenu will take care of setting the right anchor for | 834 // DownloadShelfContextMenu will take care of setting the right anchor for |
812 // the menu depending on the locale. | 835 // the menu depending on the locale. |
813 point.set_y(height()); | 836 point.set_y(height()); |
814 if (UILayoutIsRightToLeft()) | 837 if (UILayoutIsRightToLeft()) |
815 point.set_x(drop_down_x_right_); | 838 point.set_x(drop_down_x_right_); |
816 else | 839 else |
817 point.set_x(drop_down_x_left_); | 840 point.set_x(drop_down_x_left_); |
818 | 841 |
819 views::View::ConvertPointToScreen(this, &point); | 842 views::View::ConvertPointToScreen(this, &point); |
820 DownloadShelfContextMenuWin menu(model_.get(), | 843 DownloadShelfContextMenuWin menu(model_.get()); |
821 GetWidget()->GetNativeView(), | 844 |
822 point); | 845 // Protect against deletion while the menu is running. This can happen if |
| 846 // the menu is showing when an auto-opened download completes and the user |
| 847 // chooses a menu entry. |
| 848 active_menu_ = &menu; |
| 849 menu.Run(GetWidget()->GetNativeView(), point); |
| 850 |
823 // If the menu action was to remove the download, this view will also be | 851 // If the menu action was to remove the download, this view will also be |
824 // invalid so we must not access 'this' in this case. | 852 // invalid so we must not access 'this' in this case. |
825 if (menu.download()) { | 853 if (menu.download()) { |
| 854 active_menu_ = NULL; |
826 drop_down_pressed_ = false; | 855 drop_down_pressed_ = false; |
827 // Showing the menu blocks. Here we revert the state. | 856 // Showing the menu blocks. Here we revert the state. |
828 SetState(NORMAL, NORMAL); | 857 SetState(NORMAL, NORMAL); |
829 } | 858 } |
830 } | 859 } |
831 return true; | 860 return true; |
832 } | 861 } |
833 | 862 |
834 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) { | 863 void DownloadItemView::OnMouseMoved(const views::MouseEvent& event) { |
835 // Mouse should not activate us in dangerous mode. | 864 // Mouse should not activate us in dangerous mode. |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 void DownloadItemView::Reenable() { | 1023 void DownloadItemView::Reenable() { |
995 disabled_while_opening_ = false; | 1024 disabled_while_opening_ = false; |
996 SetEnabled(true); // Triggers a repaint. | 1025 SetEnabled(true); // Triggers a repaint. |
997 } | 1026 } |
998 | 1027 |
999 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { | 1028 bool DownloadItemView::InDropDownButtonXCoordinateRange(int x) { |
1000 if (x > drop_down_x_left_ && x < drop_down_x_right_) | 1029 if (x > drop_down_x_left_ && x < drop_down_x_right_) |
1001 return true; | 1030 return true; |
1002 return false; | 1031 return false; |
1003 } | 1032 } |
OLD | NEW |