Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: chrome/browser/ui/gtk/download_shelf_gtk.cc

Issue 6249022: Make the gtk download shelf autoclose on mouse out. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fewer changes Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/gtk/download_shelf_gtk.h ('k') | chrome/browser/ui/gtk/gtk_util.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 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/ui/gtk/download_shelf_gtk.h" 5 #include "chrome/browser/ui/gtk/download_shelf_gtk.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "chrome/browser/download/download_item.h" 9 #include "chrome/browser/download/download_item.h"
10 #include "chrome/browser/download/download_item_model.h" 10 #include "chrome/browser/download/download_item_model.h"
11 #include "chrome/browser/download/download_util.h" 11 #include "chrome/browser/download/download_util.h"
12 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/gtk/browser_window_gtk.h" 13 #include "chrome/browser/ui/gtk/browser_window_gtk.h"
14 #include "chrome/browser/ui/gtk/custom_button.h" 14 #include "chrome/browser/ui/gtk/custom_button.h"
15 #include "chrome/browser/ui/gtk/download_item_gtk.h" 15 #include "chrome/browser/ui/gtk/download_item_gtk.h"
16 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" 16 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
17 #include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h" 17 #include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
18 #include "chrome/browser/ui/gtk/gtk_theme_provider.h" 18 #include "chrome/browser/ui/gtk/gtk_theme_provider.h"
19 #include "chrome/browser/ui/gtk/gtk_util.h" 19 #include "chrome/browser/ui/gtk/gtk_util.h"
20 #include "chrome/common/notification_service.h" 20 #include "chrome/common/notification_service.h"
21 #include "gfx/gtk_util.h" 21 #include "gfx/gtk_util.h"
22 #include "gfx/insets.h"
23 #include "gfx/point.h"
24 #include "gfx/rect.h"
22 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
23 #include "grit/theme_resources.h" 26 #include "grit/theme_resources.h"
24 #include "ui/base/l10n/l10n_util.h" 27 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/resource/resource_bundle.h" 28 #include "ui/base/resource/resource_bundle.h"
26 29
27 namespace { 30 namespace {
28 31
29 // The height of the download items. 32 // The height of the download items.
30 const int kDownloadItemHeight = download_util::kSmallProgressIconSize; 33 const int kDownloadItemHeight = download_util::kSmallProgressIconSize;
31 34
32 // Padding between the download widgets. 35 // Padding between the download widgets.
33 const int kDownloadItemPadding = 10; 36 const int kDownloadItemPadding = 10;
34 37
35 // Padding between the top/bottom of the download widgets and the edge of the 38 // Padding between the top/bottom of the download widgets and the edge of the
36 // shelf. 39 // shelf.
37 const int kTopBottomPadding = 4; 40 const int kTopBottomPadding = 4;
38 41
39 // Padding between the left side of the shelf and the first download item. 42 // Padding between the left side of the shelf and the first download item.
40 const int kLeftPadding = 2; 43 const int kLeftPadding = 2;
41 44
42 // Padding between the right side of the shelf and the close button. 45 // Padding between the right side of the shelf and the close button.
43 const int kRightPadding = 10; 46 const int kRightPadding = 10;
44 47
45 // Speed of the shelf show/hide animation. 48 // Speed of the shelf show/hide animation.
46 const int kShelfAnimationDurationMs = 120; 49 const int kShelfAnimationDurationMs = 120;
47 50
51 // The time between when the user mouses out of the download shelf zone and
52 // when the shelf closes (when auto-close is enabled).
53 const int kAutoCloseDelayMs = 300;
54
55 // The area to the top of the shelf that is considered part of its "zone".
56 const int kShelfAuraSize = 40;
57
48 } // namespace 58 } // namespace
49 59
50 DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent) 60 DownloadShelfGtk::DownloadShelfGtk(Browser* browser, GtkWidget* parent)
51 : browser_(browser), 61 : browser_(browser),
52 is_showing_(false), 62 is_showing_(false),
53 theme_provider_(GtkThemeProvider::GetFrom(browser->profile())) { 63 theme_provider_(GtkThemeProvider::GetFrom(browser->profile())),
64 close_on_mouse_out_(false),
65 mouse_in_shelf_(false),
66 auto_close_factory_(this) {
54 // Logically, the shelf is a vbox that contains two children: a one pixel 67 // Logically, the shelf is a vbox that contains two children: a one pixel
55 // tall event box, which serves as the top border, and an hbox, which holds 68 // tall event box, which serves as the top border, and an hbox, which holds
56 // the download items and other shelf widgets (close button, show-all- 69 // the download items and other shelf widgets (close button, show-all-
57 // downloads link). 70 // downloads link).
58 // To make things pretty, we have to add a few more widgets. To get padding 71 // To make things pretty, we have to add a few more widgets. To get padding
59 // right, we stick the hbox in an alignment. We put that alignment in an 72 // right, we stick the hbox in an alignment. We put that alignment in an
60 // event box so we can color the background. 73 // event box so we can color the background.
61 74
62 // Create the top border. 75 // Create the top border.
63 top_border_ = gtk_event_box_new(); 76 top_border_ = gtk_event_box_new();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } 155 }
143 156
144 DownloadShelfGtk::~DownloadShelfGtk() { 157 DownloadShelfGtk::~DownloadShelfGtk() {
145 for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin(); 158 for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin();
146 iter != download_items_.end(); ++iter) { 159 iter != download_items_.end(); ++iter) {
147 delete *iter; 160 delete *iter;
148 } 161 }
149 162
150 shelf_.Destroy(); 163 shelf_.Destroy();
151 items_hbox_.Destroy(); 164 items_hbox_.Destroy();
165
166 // Make sure we're no longer an observer of the message loop.
167 SetCloseOnMouseOut(false);
152 } 168 }
153 169
154 void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) { 170 void DownloadShelfGtk::AddDownload(BaseDownloadItemModel* download_model_) {
155 download_items_.push_back(new DownloadItemGtk(this, download_model_)); 171 download_items_.push_back(new DownloadItemGtk(this, download_model_));
156 Show(); 172 Show();
157 } 173 }
158 174
159 bool DownloadShelfGtk::IsShowing() const { 175 bool DownloadShelfGtk::IsShowing() const {
160 return slide_widget_->IsShowing(); 176 return slide_widget_->IsShowing();
161 } 177 }
162 178
163 bool DownloadShelfGtk::IsClosing() const { 179 bool DownloadShelfGtk::IsClosing() const {
164 return slide_widget_->IsClosing(); 180 return slide_widget_->IsClosing();
165 } 181 }
166 182
167 void DownloadShelfGtk::Show() { 183 void DownloadShelfGtk::Show() {
168 slide_widget_->Open(); 184 slide_widget_->Open();
169 browser_->UpdateDownloadShelfVisibility(true); 185 browser_->UpdateDownloadShelfVisibility(true);
186 CancelAutoClose();
170 } 187 }
171 188
172 void DownloadShelfGtk::Close() { 189 void DownloadShelfGtk::Close() {
173 // When we are closing, we can vertically overlap the render view. Make sure 190 // When we are closing, we can vertically overlap the render view. Make sure
174 // we are on top. 191 // we are on top.
175 gdk_window_raise(shelf_.get()->window); 192 gdk_window_raise(shelf_.get()->window);
176 slide_widget_->Close(); 193 slide_widget_->Close();
177 browser_->UpdateDownloadShelfVisibility(false); 194 browser_->UpdateDownloadShelfVisibility(false);
195 SetCloseOnMouseOut(false);
178 } 196 }
179 197
180 Browser* DownloadShelfGtk::browser() const { 198 Browser* DownloadShelfGtk::browser() const {
181 return browser_; 199 return browser_;
182 } 200 }
183 201
184 void DownloadShelfGtk::Closed() { 202 void DownloadShelfGtk::Closed() {
185 // When the close animation is complete, remove all completed downloads. 203 // When the close animation is complete, remove all completed downloads.
186 size_t i = 0; 204 size_t i = 0;
187 while (i < download_items_.size()) { 205 while (i < download_items_.size()) {
188 DownloadItem* download = download_items_[i]->get_download(); 206 DownloadItem* download = download_items_[i]->get_download();
189 bool is_transfer_done = download->state() == DownloadItem::COMPLETE || 207 bool is_transfer_done = download->state() == DownloadItem::COMPLETE ||
190 download->state() == DownloadItem::CANCELLED; 208 download->state() == DownloadItem::CANCELLED;
191 if (is_transfer_done && 209 if (is_transfer_done &&
192 download->safety_state() != DownloadItem::DANGEROUS) { 210 download->safety_state() != DownloadItem::DANGEROUS) {
193 RemoveDownloadItem(download_items_[i]); 211 RemoveDownloadItem(download_items_[i]);
194 } else { 212 } else {
213 // We set all remaining items as "opened", so that the shelf will auto-
214 // close in the future without the user clicking on them.
215 download->set_opened(true);
195 ++i; 216 ++i;
196 } 217 }
197 } 218 }
198 } 219 }
199 220
200 void DownloadShelfGtk::Observe(NotificationType type, 221 void DownloadShelfGtk::Observe(NotificationType type,
201 const NotificationSource& source, 222 const NotificationSource& source,
202 const NotificationDetails& details) { 223 const NotificationDetails& details) {
203 if (type == NotificationType::BROWSER_THEME_CHANGED) { 224 if (type == NotificationType::BROWSER_THEME_CHANGED) {
204 GdkColor color = theme_provider_->GetGdkColor( 225 GdkColor color = theme_provider_->GetGdkColor(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) { 260 void DownloadShelfGtk::RemoveDownloadItem(DownloadItemGtk* download_item) {
240 DCHECK(download_item); 261 DCHECK(download_item);
241 std::vector<DownloadItemGtk*>::iterator i = 262 std::vector<DownloadItemGtk*>::iterator i =
242 find(download_items_.begin(), download_items_.end(), download_item); 263 find(download_items_.begin(), download_items_.end(), download_item);
243 DCHECK(i != download_items_.end()); 264 DCHECK(i != download_items_.end());
244 download_items_.erase(i); 265 download_items_.erase(i);
245 delete download_item; 266 delete download_item;
246 if (download_items_.empty()) { 267 if (download_items_.empty()) {
247 slide_widget_->CloseWithoutAnimation(); 268 slide_widget_->CloseWithoutAnimation();
248 browser_->UpdateDownloadShelfVisibility(false); 269 browser_->UpdateDownloadShelfVisibility(false);
270 } else {
271 AutoCloseIfPossible();
249 } 272 }
250 } 273 }
251 274
252 GtkWidget* DownloadShelfGtk::GetHBox() const { 275 GtkWidget* DownloadShelfGtk::GetHBox() const {
253 return items_hbox_.get(); 276 return items_hbox_.get();
254 } 277 }
255 278
256 void DownloadShelfGtk::MaybeShowMoreDownloadItems() { 279 void DownloadShelfGtk::MaybeShowMoreDownloadItems() {
257 // Show all existing download items. It'll trigger "size-allocate" signal, 280 // Show all existing download items. It'll trigger "size-allocate" signal,
258 // which will hide download items that don't have enough space to show. 281 // which will hide download items that don't have enough space to show.
259 gtk_widget_show_all(items_hbox_.get()); 282 gtk_widget_show_all(items_hbox_.get());
260 } 283 }
261 284
262 void DownloadShelfGtk::OnButtonClick(GtkWidget* button) { 285 void DownloadShelfGtk::OnButtonClick(GtkWidget* button) {
263 if (button == close_button_->widget()) { 286 if (button == close_button_->widget()) {
264 Close(); 287 Close();
265 } else { 288 } else {
266 // The link button was clicked. 289 // The link button was clicked.
267 browser_->ShowDownloadsTab(); 290 browser_->ShowDownloadsTab();
268 } 291 }
269 } 292 }
293
294 void DownloadShelfGtk::AutoCloseIfPossible() {
295 for (std::vector<DownloadItemGtk*>::iterator iter = download_items_.begin();
296 iter != download_items_.end(); ++iter) {
297 if (!(*iter)->get_download()->opened())
298 return;
299 }
300
301 SetCloseOnMouseOut(true);
302 }
303
304 void DownloadShelfGtk::CancelAutoClose() {
305 SetCloseOnMouseOut(false);
306 auto_close_factory_.RevokeAll();
307 }
308
309 void DownloadShelfGtk::ItemOpened() {
310 AutoCloseIfPossible();
311 }
312
313 void DownloadShelfGtk::SetCloseOnMouseOut(bool close) {
314 if (close_on_mouse_out_ == close)
315 return;
316
317 close_on_mouse_out_ = close;
318 mouse_in_shelf_ = close;
319 if (close)
320 MessageLoopForUI::current()->AddObserver(this);
321 else
322 MessageLoopForUI::current()->RemoveObserver(this);
323 }
324
325 void DownloadShelfGtk::WillProcessEvent(GdkEvent* event) {
326 }
327
328 void DownloadShelfGtk::DidProcessEvent(GdkEvent* event) {
329 gfx::Point cursor_screen_coords;
330
331 switch (event->type) {
332 case GDK_MOTION_NOTIFY:
333 cursor_screen_coords =
334 gfx::Point(event->motion.x_root, event->motion.y_root);
335 break;
336 case GDK_LEAVE_NOTIFY:
337 cursor_screen_coords =
338 gfx::Point(event->crossing.x_root, event->crossing.y_root);
339 break;
340 default:
341 return;
342 }
343
344 bool mouse_in_shelf = IsCursorInShelfZone(cursor_screen_coords);
345 if (mouse_in_shelf == mouse_in_shelf_)
346 return;
347 mouse_in_shelf_ = mouse_in_shelf;
348
349 if (mouse_in_shelf)
350 MouseEnteredShelf();
351 else
352 MouseLeftShelf();
353 }
354
355 bool DownloadShelfGtk::IsCursorInShelfZone(
356 const gfx::Point& cursor_screen_coords) {
357 gfx::Rect bounds(gtk_util::GetWidgetScreenPosition(shelf_.get()),
358 gfx::Size(shelf_.get()->allocation.width,
359 shelf_.get()->allocation.height));
360
361 // Negative insets expand the rectangle. We only expand the top.
362 bounds.Inset(gfx::Insets(-kShelfAuraSize, 0, 0, 0));
363
364 return bounds.Contains(cursor_screen_coords);
365 }
366
367 void DownloadShelfGtk::MouseLeftShelf() {
368 DCHECK(close_on_mouse_out_);
369
370 MessageLoop::current()->PostDelayedTask(
371 FROM_HERE,
372 auto_close_factory_.NewRunnableMethod(&DownloadShelfGtk::Close),
373 kAutoCloseDelayMs);
374 }
375
376 void DownloadShelfGtk::MouseEnteredShelf() {
377 auto_close_factory_.RevokeAll();
378 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/gtk/download_shelf_gtk.h ('k') | chrome/browser/ui/gtk/gtk_util.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698