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

Side by Side Diff: ash/system/drive/tray_drive.cc

Issue 10214013: Created uber tray UI for monitoring ongoing WebDrive sync operations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 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
OLDNEW
(Empty)
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 #include "ash/system/drive/tray_drive.h"
6
7 #include <vector>
8
9 #include "ash/shell.h"
10 #include "ash/system/tray/system_tray.h"
11 #include "ash/system/tray/system_tray_delegate.h"
12 #include "ash/system/tray/tray_constants.h"
13 #include "ash/system/tray/tray_item_more.h"
14 #include "ash/system/tray/tray_item_view.h"
15 #include "ash/system/tray/tray_views.h"
16 #include "base/logging.h"
17 #include "base/string_number_conversions.h"
18 #include "base/utf_string_conversions.h"
19 #include "base/stl_util.h"
20 #include "grit/ash_strings.h"
21 #include "grit/ui_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/gfx/font.h"
25 #include "ui/gfx/image/image.h"
26 #include "ui/views/controls/button/image_button.h"
27 #include "ui/views/controls/label.h"
28 #include "ui/views/controls/progress_bar.h"
29 #include "ui/views/layout/box_layout.h"
30 #include "ui/views/layout/grid_layout.h"
31
32 string16 GetTrayLabel(const ash::DriveOperationStatusList& list) {
sadrul 2012/05/01 14:28:58 These two functions should either be static or in
zel 2012/05/01 16:56:52 Done.
33 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DRIVE_SYNCING,
34 base::IntToString16(static_cast<int>(list.size())));
35 }
36
37 ash::DriveOperationStatusList* GetCurrentOperationList() {
38 ash::SystemTrayDelegate* delegate =
39 ash::Shell::GetInstance()->tray_delegate();
40 ash::DriveOperationStatusList* list = new ash::DriveOperationStatusList();
41 delegate->GetDriveOperationStatusList(list);
42 return list;
43 }
44
45 namespace ash {
46
47 namespace internal {
48
49 namespace tray {
50
51 const int kSidePadding = 8;
52 const int kHorizontalPadding = 6;
53 const int kVerticalPadding = 6;
54 const int kProgressBarWidth = 100;
55 const int kProgressBarHeight = 8;
56
57 class DriveDefaultView : public TrayItemMore {
58 public:
59 explicit DriveDefaultView(SystemTrayItem* owner,
xiyuan 2012/05/01 16:47:53 nit: no need to have "explicit" when having more t
zel 2012/05/01 16:56:52 Done.
60 const DriveOperationStatusList* list)
61 : TrayItemMore(owner) {
62 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
63
64 SetImage(bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DRIVE).ToSkBitmap());
65 Update(list);
66 }
67
68 virtual ~DriveDefaultView() {}
69
70 void Update(const DriveOperationStatusList* list) {
71 DCHECK(list);
72 string16 label = GetTrayLabel(*list);
73 SetLabel(label);
74 SetAccessibleName(label);
75 }
76
77 private:
78 DISALLOW_COPY_AND_ASSIGN(DriveDefaultView);
79 };
80
81 class DriveDetailedView : public views::View,
82 public ViewClickListener {
83 public:
84 DriveDetailedView(SystemTrayItem* owner,
85 const DriveOperationStatusList* list)
86 : header_(NULL), operations_(NULL), settings_(NULL),
87 in_progress_img_(NULL), done_img_(NULL), failed_img_(NULL) {
sadrul 2012/05/01 14:28:58 Each in its own line.
zel 2012/05/01 16:56:52 Done.
88 SetLayoutManager(new views::BoxLayout(
89 views::BoxLayout::kVertical, 0, 0, 0));
90 set_background(views::Background::CreateSolidBackground(kBackgroundColor));
91
92 in_progress_img_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
93 IDR_AURA_UBER_TRAY_DRIVE);
94 done_img_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
95 IDR_AURA_UBER_TRAY_DRIVE_DONE);
96 failed_img_ = ResourceBundle::GetSharedInstance().GetBitmapNamed(
97 IDR_AURA_UBER_TRAY_DRIVE_FAILED);
98
99 Update(list);
100 }
101
102 virtual ~DriveDetailedView() {
103 STLDeleteValues(&update_map_);
104 }
105
106 void Update(const DriveOperationStatusList* list) {
107 AppendHeaderEntry(list);
108 AppendOperationList(list);
109 // AppendSettings();
sadrul 2012/05/01 14:28:58 Left out intentionally?
zel 2012/05/01 16:56:52 Done.
110 ChildPreferredSizeChanged(operations_);
111 SchedulePaint();
112 }
113
114 private:
115 class OperationProgressBar : public views::ProgressBar {
116 public:
117 OperationProgressBar() {}
118 private:
119
xiyuan 2012/05/01 16:47:53 nit: empty line before "private:"?
zel 2012/05/01 16:56:52 Done.
120 // Overridden from View:
121 virtual gfx::Size GetPreferredSize() OVERRIDE {
122 return gfx::Size(kProgressBarWidth, kProgressBarHeight);
123 }
124 };
sadrul 2012/05/01 14:28:58 DISALLOW_COPY_AND_ASSIGN
zel 2012/05/01 16:56:52 Done.
125
126 class RowView : public views::View,
127 public views::ButtonListener {
128 public:
129 RowView(DriveDetailedView* parent,
130 ash::DriveOperationStatus::OperationState state,
131 double progress,
132 const FilePath& file_path)
133 : parent_(parent), status_img_(NULL), label_container_(NULL),
134 progress_bar_(NULL), cancel_button_(NULL), file_path_(file_path) {
sadrul 2012/05/01 14:28:58 each in its own line
zel 2012/05/01 16:56:52 Done.
135 // Status image.
136 status_img_ = new views::ImageView();
137 status_img_->set_focusable(false);
xiyuan 2012/05/01 16:47:53 nit: probably don't need this as ImageView is not
zel 2012/05/01 16:56:52 Done.
138 AddChildView(status_img_);
139
140 label_container_ = new views::View();
141 label_container_->SetLayoutManager(new views::BoxLayout(
142 views::BoxLayout::kVertical, 0, 0, kVerticalPadding));
143 views::Label* label = new views::Label(
144 UTF8ToUTF16(file_path.BaseName().value()));
145 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
146 label_container_->AddChildView(label);
147 // Add progress bar.
148 progress_bar_ = new OperationProgressBar();
149 label_container_->AddChildView(progress_bar_);
150
151 AddChildView(label_container_);
152
153 cancel_button_ = new views::ImageButton(this);
154 cancel_button_->set_focusable(false);
xiyuan 2012/05/01 16:47:53 nit: probably don't need this as ImageButton/Custo
zel 2012/05/01 16:56:52 Done.
155 cancel_button_->SetImage(views::ImageButton::BS_NORMAL,
156 ResourceBundle::GetSharedInstance().GetBitmapNamed(
157 IDR_AURA_UBER_TRAY_DRIVE_CANCEL));
158
159 UpdateStatus(parent_, state, progress);
160 AddChildView(cancel_button_);
161 }
162
163 void UpdateStatus(DriveDetailedView* parent,
xiyuan 2012/05/01 16:47:53 nit: since we have member parent_ now, probably do
zel 2012/05/01 16:56:52 Done.
zel 2012/05/01 16:56:52 Done.
164 ash::DriveOperationStatus::OperationState state,
165 double progress) {
166 status_img_->SetImage(parent->GetImageForState(state));
167 progress_bar_->SetValue(progress);
168 cancel_button_->SetVisible(
169 state == ash::DriveOperationStatus::OPERATION_IN_PROGRESS ||
170 state == ash::DriveOperationStatus::OPERATION_SUSPENDED);
171 }
172
173 private:
174
xiyuan 2012/05/01 16:47:53 nit: nuke this empty line?
175 // views::View overrides.
176 virtual gfx::Size GetPreferredSize() OVERRIDE {
177 return gfx::Size(
178 status_img_->GetPreferredSize().width() +
179 label_container_->GetPreferredSize().width() +
180 cancel_button_->GetPreferredSize().width() +
181 2 * kSidePadding + 2 * kHorizontalPadding,
182 std::max(status_img_->GetPreferredSize().height(),
183 std::max(label_container_->GetPreferredSize().height(),
184 cancel_button_->GetPreferredSize().height())) +
185 2 * kVerticalPadding);
186
xiyuan 2012/05/01 16:47:53 nit: nuke this empty line?
zel 2012/05/01 16:56:52 Done.
187 }
188
189 virtual void Layout() OVERRIDE {
190 gfx::Rect child_area(GetLocalBounds());
191 if (child_area.IsEmpty())
192 return;
193
194 int pos_x = child_area.x() + kSidePadding;
195 int pos_y = child_area.y() + kVerticalPadding;
196
197 gfx::Rect bounds_status(
198 gfx::Point(pos_x,
199 (child_area.height() - 2 * kVerticalPadding -
200 label_container_->GetPreferredSize().height())/2),
201 status_img_->GetPreferredSize());
202 status_img_->SetBoundsRect(bounds_status.Intersect(child_area));
203 pos_x += status_img_->GetPreferredSize().width() + kHorizontalPadding;
xiyuan 2012/05/01 16:47:53 nit: status_img_->GetPreferredSize().width() -> st
zel 2012/05/01 16:56:52 Done.
204
205 gfx::Rect bounds_label(pos_x, pos_y,
xiyuan 2012/05/01 16:47:53 nit: pos_y on its own line
206 child_area.width() - 2 * kSidePadding -
207 2 * kHorizontalPadding -
208 status_img_->GetPreferredSize().width() -
209 cancel_button_->GetPreferredSize().width(),
xiyuan 2012/05/01 16:47:53 nit: indent above 3 lines to make it clear that th
zel 2012/05/01 16:56:52 Done.
210 label_container_->GetPreferredSize().height());
211 label_container_->SetBoundsRect(bounds_label.Intersect(child_area));
212 pos_x += label_container_->bounds().width() + kHorizontalPadding;
213
214 gfx::Rect bounds_button(
215 gfx::Point(pos_x,
216 (child_area.height() - 2 * kVerticalPadding -
217 label_container_->GetPreferredSize().height())/2),
218 cancel_button_->GetPreferredSize());
219 cancel_button_->SetBoundsRect(bounds_button.Intersect(child_area));
220 }
221
222 // views::ButtonListener overrides.
223 virtual void ButtonPressed(views::Button* sender,
224 const views::Event& event) OVERRIDE {
225 DCHECK(sender == cancel_button_);
226 parent_->OnCancelOperation(file_path_);
227 }
228
229 DriveDetailedView* parent_;
230 views::ImageView* status_img_;
231 views::View* label_container_;
232 views::ProgressBar* progress_bar_;
233 views::ImageButton* cancel_button_;
234 FilePath file_path_;
235 };
sadrul 2012/05/01 14:28:58 DISALLOW_COPY_AND_ASSIGN
zel 2012/05/01 16:56:52 Done.
236
237 struct OperationItem {
xiyuan 2012/05/01 16:47:53 nit: Is this still in use?
zel 2012/05/01 16:56:52 Done.
238 OperationItem(RowView* row_view,
239 views::ImageView* status_img,
240 views::ProgressBar* progress_bar,
241 views::ImageButton* cancel_button)
242 : row_view(row_view),
243 status_img(status_img),
244 progress_bar(progress_bar),
245 cancel_button(cancel_button) {
246 }
247 RowView* row_view;
248 views::ImageView* status_img;
249 views::ProgressBar* progress_bar;
250 views::ImageButton* cancel_button;
251 };
252
253 void AppendHeaderEntry(const DriveOperationStatusList* list) {
254 if (header_)
255 return;
256 header_ = CreateDetailedHeaderEntry(IDS_ASH_STATUS_TRAY_DRIVE, this);
257 AddChildView(header_);
258 }
259
260 SkBitmap* GetImageForState(ash::DriveOperationStatus::OperationState state) {
261 switch (state) {
262 case ash::DriveOperationStatus::OPERATION_NOT_STARTED:
263 case ash::DriveOperationStatus::OPERATION_STARTED:
264 case ash::DriveOperationStatus::OPERATION_IN_PROGRESS:
265 case ash::DriveOperationStatus::OPERATION_SUSPENDED:
266 return in_progress_img_;
267 case ash::DriveOperationStatus::OPERATION_COMPLETED:
268 return done_img_;
269 case ash::DriveOperationStatus::OPERATION_FAILED:
270 return failed_img_;
271 }
272 return failed_img_;
273 }
274
275 virtual void OnCancelOperation(const FilePath& file_path) {
276 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
277 delegate->CancelDriveOperation(file_path);
278 }
279
280 void AppendOperationList(const DriveOperationStatusList* list) {
281 views::BoxLayout* layout = NULL;
282 if (!operations_) {
283 operations_ = new views::View;
284 layout = new views::BoxLayout(
285 views::BoxLayout::kVertical, 0, 0, 1);
286 operations_->SetLayoutManager(layout);
287 AddChildView(operations_);
288 } else {
289 layout = reinterpret_cast<views::BoxLayout*>(
290 operations_->GetLayoutManager());
sadrul 2012/05/01 14:28:58 It doesn't look like layout is used after this. So
zel 2012/05/01 16:56:52 Done.
291 }
292
293 // Apply the update.
294 std::set<FilePath> new_set;
295 for (DriveOperationStatusList::const_iterator it = list->begin();
296 it != list->end(); ++it) {
297 const DriveOperationStatus& operation = *it;
298
299 new_set.insert(operation.file_path);
300 std::map<FilePath, RowView*>::iterator existing_item =
301 update_map_.find(operation.file_path);
302
303 if (existing_item != update_map_.end()) {
304 existing_item->second->UpdateStatus(this,
305 operation.state,
306 operation.progress);
307 } else {
308 RowView* row_view = new RowView(this,
309 operation.state,
310 operation.progress,
311 operation.file_path);
312
313 update_map_[operation.file_path] = row_view;
314 operations_->AddChildView(row_view);
315 }
316 }
317
318 // Remove items from the list that haven't been added or modified with this
319 // update batch.
320 std::set<FilePath> remove_set;
321 for (std::map<FilePath, RowView*>::iterator update_iter =
322 update_map_.begin();
323 update_iter != update_map_.end(); ++update_iter) {
324 if (new_set.find(update_iter->first) == new_set.end()) {
325 remove_set.insert(update_iter->first);
326 }
327 }
328
329 for (std::set<FilePath>::iterator removed_iter = remove_set.begin();
330 removed_iter != remove_set.end(); ++removed_iter) {
331 delete update_map_[*removed_iter];
332 update_map_.erase(*removed_iter);
333 }
334 }
335
336 void AppendSettings() {
337 HoverHighlightView* container = new HoverHighlightView(this);
338 container->set_fixed_height(kTrayPopupItemHeight);
339 container->AddLabel(ui::ResourceBundle::GetSharedInstance().
340 GetLocalizedString(IDS_ASH_STATUS_TRAY_DRIVE_SETTINGS),
341 gfx::Font::NORMAL);
342 AddChildView(container);
343 settings_ = container;
344 }
345
346 // Overridden from ViewClickListener.
347 virtual void ClickedOn(views::View* sender) OVERRIDE {
348 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate();
349 if (sender == header_) {
350 Shell::GetInstance()->tray()->ShowDefaultView();
351 } else if (sender == settings_) {
352 delegate->ShowDriveSettings();
353 }
354 }
xiyuan 2012/05/01 16:47:53 nit: insert an empty line
zel 2012/05/01 16:56:52 Done.
355 // Maps operation entries to their file paths.
356 std::map<FilePath, RowView*> update_map_;
357 views::View* header_;
358 views::View* operations_;
359 views::View* settings_;
360 SkBitmap* in_progress_img_;
361 SkBitmap* done_img_;
362 SkBitmap* failed_img_;
363
364 DISALLOW_COPY_AND_ASSIGN(DriveDetailedView);
365 };
366
367 } // namespace tray
368
369 TrayDrive::TrayDrive() : TrayImageItem(IDR_AURA_UBER_TRAY_DRIVE_LIGHT) {
370 }
371
372 bool TrayDrive::GetInitialVisibility() {
373 scoped_ptr<DriveOperationStatusList> list(GetCurrentOperationList());
sadrul 2012/05/01 14:28:58 Is there a chance the tray can show up when logged
zel 2012/05/01 16:56:52 Nope. The user needs to be fully authenticated and
374 return list->size() > 0;
375 }
376
377 TrayDrive::~TrayDrive() {
xiyuan 2012/05/01 16:47:53 nit: move this up to keep the same order as in hea
zel 2012/05/01 16:56:52 Done.
378 }
379
380 views::View* TrayDrive::CreateDefaultView(user::LoginStatus status) {
381 if (status != user::LOGGED_IN_USER && status != user::LOGGED_IN_OWNER)
382 return NULL;
383
384 scoped_ptr<DriveOperationStatusList> list(GetCurrentOperationList());
385 if (!list->size())
386 return NULL;
387
388 default_.reset(new tray::DriveDefaultView(this, list.get()));
389 return default_.get();
390 }
391
392 views::View* TrayDrive::CreateDetailedView(user::LoginStatus status) {
393 if (status != user::LOGGED_IN_USER && status != user::LOGGED_IN_OWNER)
394 return NULL;
395
396 scoped_ptr<DriveOperationStatusList> list(GetCurrentOperationList());
397 if (!list->size())
398 return NULL;
399
400 detailed_.reset(new tray::DriveDetailedView(this, list.get()));
401 return detailed_.get();
402 }
403
404 void TrayDrive::DestroyDefaultView() {
405 default_.reset();
406 }
407
408 void TrayDrive::DestroyDetailedView() {
409 detailed_.reset();
410 }
411
412 void TrayDrive::UpdateAfterLoginStatusChange(user::LoginStatus status) {
413 if (status == user::LOGGED_IN_USER || status == user::LOGGED_IN_OWNER)
414 return;
415
416 tray_view()->SetVisible(false);
417 DestroyDefaultView();
418 DestroyDetailedView();
419 }
420
421 void TrayDrive::OnDriveRefresh(const DriveOperationStatusList& list) {
422 tray_view()->SetVisible(list.size() > 0);
423 tray_view()->SchedulePaint();
424
425 if (default_.get())
426 default_->Update(&list);
427
428 if (detailed_.get())
429 detailed_->Update(&list);
430 }
431
432 } // namespace internal
433 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698