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

Side by Side Diff: chrome/browser/ui/views/web_intent_picker_views.cc

Issue 9959130: [Web Intents] Display throbber when loading inline disposition. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix unit_tests Created 8 years, 8 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/intents/web_intent_picker.h ('k') | no next file » | 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) 2012 The Chromium Authors. All rights reserved. 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 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 <algorithm> 5 #include <algorithm>
6 #include <vector> 6 #include <vector>
7 7
8 #include "base/time.h"
8 #include "base/memory/scoped_vector.h" 9 #include "base/memory/scoped_vector.h"
9 #include "chrome/browser/ui/browser.h" 10 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_navigator.h" 11 #include "chrome/browser/ui/browser_navigator.h"
11 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h" 12 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h"
12 #include "chrome/browser/ui/intents/web_intent_picker.h" 13 #include "chrome/browser/ui/intents/web_intent_picker.h"
13 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" 14 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
14 #include "chrome/browser/ui/intents/web_intent_picker_model.h" 15 #include "chrome/browser/ui/intents/web_intent_picker_model.h"
15 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" 16 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h"
16 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 17 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
17 #include "chrome/browser/ui/views/constrained_window_views.h" 18 #include "chrome/browser/ui/views/constrained_window_views.h"
18 #include "chrome/browser/ui/views/frame/browser_view.h" 19 #include "chrome/browser/ui/views/frame/browser_view.h"
19 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" 20 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
20 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h" 21 #include "chrome/browser/ui/views/tab_contents/tab_contents_container.h"
21 #include "chrome/browser/ui/views/toolbar_view.h" 22 #include "chrome/browser/ui/views/toolbar_view.h"
22 #include "chrome/browser/ui/views/window.h" 23 #include "chrome/browser/ui/views/window.h"
23 #include "chrome/common/extensions/extension_constants.h" 24 #include "chrome/common/extensions/extension_constants.h"
24 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
25 #include "content/public/browser/web_contents_view.h" 26 #include "content/public/browser/web_contents_view.h"
26 #include "grit/chromium_strings.h" 27 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h" 28 #include "grit/generated_resources.h"
28 #include "grit/google_chrome_strings.h" 29 #include "grit/google_chrome_strings.h"
29 #include "grit/theme_resources.h" 30 #include "grit/theme_resources.h"
31 #include "grit/ui_resources.h"
30 #include "grit/ui_resources_standard.h" 32 #include "grit/ui_resources_standard.h"
31 #include "third_party/skia/include/core/SkColor.h" 33 #include "third_party/skia/include/core/SkColor.h"
32 #include "ui/base/l10n/l10n_util.h" 34 #include "ui/base/l10n/l10n_util.h"
33 #include "ui/base/resource/resource_bundle.h" 35 #include "ui/base/resource/resource_bundle.h"
34 #include "ui/base/text/text_elider.h" 36 #include "ui/base/text/text_elider.h"
35 #include "ui/gfx/canvas.h" 37 #include "ui/gfx/canvas.h"
36 #include "ui/gfx/image/image.h" 38 #include "ui/gfx/image/image.h"
37 #include "ui/views/border.h" 39 #include "ui/views/border.h"
38 #include "ui/views/controls/button/image_button.h" 40 #include "ui/views/controls/button/image_button.h"
39 #include "ui/views/controls/button/text_button.h" 41 #include "ui/views/controls/button/text_button.h"
(...skipping 29 matching lines...) Expand all
69 71
70 // The maximum width in pixels of a suggested extension's title link. 72 // The maximum width in pixels of a suggested extension's title link.
71 const int kTitleLinkMaxWidth = 130; 73 const int kTitleLinkMaxWidth = 130;
72 74
73 // The color used to dim disabled elements. 75 // The color used to dim disabled elements.
74 const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255); 76 const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255);
75 77
76 // The color used to display a disabled link. 78 // The color used to display a disabled link.
77 const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128); 79 const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128);
78 80
81 // The time between successive throbber frames in milliseconds.
82 const int kThrobberFrameTimeMs = 60;
83
79 // Enables or disables all child views of |view|. 84 // Enables or disables all child views of |view|.
80 void EnableChildViews(views::View* view, bool enabled) { 85 void EnableChildViews(views::View* view, bool enabled) {
81 for (int i = 0; i < view->child_count(); ++i) { 86 for (int i = 0; i < view->child_count(); ++i) {
82 views::View* child = view->child_at(i); 87 views::View* child = view->child_at(i);
83 child->SetEnabled(enabled); 88 child->SetEnabled(enabled);
84 } 89 }
85 } 90 }
86 91
87 // StarsView ------------------------------------------------------------------- 92 // StarsView -------------------------------------------------------------------
88 93
(...skipping 29 matching lines...) Expand all
118 // TODO(binji): Add tooltip with text rating 123 // TODO(binji): Add tooltip with text rating
119 // "Average Rating: X.XX stars (YYYYY)" 124 // "Average Rating: X.XX stars (YYYYY)"
120 // Y = "1: Hated it, 2: Disliked it, 3: It was okay, 4: Liked it, 125 // Y = "1: Hated it, 2: Disliked it, 3: It was okay, 4: Liked it,
121 // 5: Loved it" 126 // 5: Loved it"
122 // Choose Y based on rounded X. 127 // Choose Y based on rounded X.
123 } 128 }
124 129
125 StarsView::~StarsView() { 130 StarsView::~StarsView() {
126 } 131 }
127 132
133 // ThrobberNativeTextButton ----------------------------------------------------
134
135 // A native text button that can display a throbber in place of its icon. Much
136 // of the logic of this class is copied from ui/views/controls/throbber.h.
137 class ThrobberNativeTextButton : public views::NativeTextButton {
138 public:
139 ThrobberNativeTextButton(views::ButtonListener* listener,
140 const string16& text);
141 ~ThrobberNativeTextButton();
sky 2012/04/13 21:36:16 virtual
binji 2012/04/13 22:27:33 Done.
142
143 // Start or stop the throbber.
144 void StartThrobber();
145 void StopThrobber();
146
147 // Set the throbber bitmap to use. IDR_THROBBER is used by default.
148 void SetFrames(const SkBitmap* frames);
149
150 protected:
151 virtual const SkBitmap& GetImageToPaint() const OVERRIDE;
152
153 private:
154 // The timer callback to schedule painting this view.
155 void Run();
156
157 // Bitmap that contains the throbber frames.
158 const SkBitmap* frames_;
159
160 // The currently displayed frame, given to GetImageToPaint.
161 mutable SkBitmap this_frame_;
162
163 // How long one frame is displayed.
164 base::TimeDelta frame_time_;
165
166 // Used to schedule Run calls.
167 base::RepeatingTimer<ThrobberNativeTextButton> timer_;
168
169 // How many frames we have.
170 int frame_count_;
171
172 // Time when StartThrobber was called.
173 base::Time start_time_;
sky 2012/04/13 21:36:16 Use TimeTicks.
binji 2012/04/13 22:27:33 Done.
174
175 // Whether the throbber is shown an animating.
176 bool running_;
177 };
sky 2012/04/13 21:36:16 DISALLOW_
binji 2012/04/13 22:27:33 Done.
178
179 ThrobberNativeTextButton::ThrobberNativeTextButton(
180 views::ButtonListener* listener, const string16& text)
181 : NativeTextButton(listener, text),
182 frame_time_(base::TimeDelta::FromMilliseconds(kThrobberFrameTimeMs)),
183 frame_count_(0),
184 running_(false) {
185 SetFrames(ui::ResourceBundle::GetSharedInstance().GetImageNamed(
186 IDR_THROBBER).ToSkBitmap());
187 }
188
189 ThrobberNativeTextButton::~ThrobberNativeTextButton() {
190 StopThrobber();
191 }
192
193 void ThrobberNativeTextButton::StartThrobber() {
194 if (running_)
195 return;
196
197 start_time_ = base::Time::Now();
198 timer_.Start(FROM_HERE, frame_time_ - base::TimeDelta::FromMilliseconds(10),
sky 2012/04/13 21:36:16 Why the -10ms here?
binji 2012/04/13 22:27:33 Not sure, this was copy/paste from views/controls/
199 this, &ThrobberNativeTextButton::Run);
200 running_ = true;
201
202 SchedulePaint();
203 }
204
205 void ThrobberNativeTextButton::StopThrobber() {
206 if (!running_)
207 return;
208
209 timer_.Stop();
210 running_ = false;
211 }
212
213 void ThrobberNativeTextButton::SetFrames(const SkBitmap* frames) {
214 frames_ = frames;
215 DCHECK(frames_->width() > 0 && frames_->height() > 0);
216 DCHECK(frames_->width() % frames_->height() == 0);
217 frame_count_ = frames_->width() / frames_->height();
218 PreferredSizeChanged();
219 }
220
221 const SkBitmap& ThrobberNativeTextButton::GetImageToPaint() const {
222 if (!running_)
223 return NativeTextButton::GetImageToPaint();
224
225 const base::TimeDelta elapsed_time = base::Time::Now() - start_time_;
226 const int current_frame =
227 static_cast<int>(elapsed_time / frame_time_) % frame_count_;
sky 2012/04/13 21:36:16 nit: indent 4
binji 2012/04/13 22:27:33 Done.
228 const int image_size = frames_->height();
229 const int image_offset = current_frame * image_size;
230
231 SkIRect subset_rect = SkIRect::MakeXYWH(image_offset, 0,
232 image_size, image_size);
233 frames_->extractSubset(&this_frame_, subset_rect);
234 return this_frame_;
235 }
236
237 void ThrobberNativeTextButton::Run() {
238 DCHECK(running_);
239
240 SchedulePaint();
241 }
242
128 // ServiceButtonsView ---------------------------------------------------------- 243 // ServiceButtonsView ----------------------------------------------------------
129 244
130 // A view that contains all service buttons (i.e. the installed services). 245 // A view that contains all service buttons (i.e. the installed services).
131 class ServiceButtonsView : public views::View, 246 class ServiceButtonsView : public views::View,
132 public views::ButtonListener { 247 public views::ButtonListener {
133 public: 248 public:
134 class Delegate { 249 class Delegate {
135 public: 250 public:
136 // Called when a service button is clicked. |index| is the index of the 251 // Called when a service button is clicked. |index| is the index of the
137 // service button in the model. 252 // service button in the model.
138 virtual void OnServiceButtonClicked( 253 virtual void OnServiceButtonClicked(
139 const WebIntentPickerModel::InstalledService& service) = 0; 254 const WebIntentPickerModel::InstalledService& service) = 0;
140 255
141 protected: 256 protected:
142 virtual ~Delegate() {} 257 virtual ~Delegate() {}
143 }; 258 };
144 259
145 ServiceButtonsView(const WebIntentPickerModel* model, Delegate* delegate); 260 ServiceButtonsView(const WebIntentPickerModel* model, Delegate* delegate);
146 virtual ~ServiceButtonsView(); 261 virtual ~ServiceButtonsView();
147 262
148 // Updates the service button view with new model data. 263 // Updates the service button view with new model data.
149 void Update(); 264 void Update();
150 265
266 // Start a throbber on the service button that will launch the service at
267 // |url|.
268 void StartThrobber(const GURL& url);
269
151 // views::ButtonListener implementation. 270 // views::ButtonListener implementation.
152 virtual void ButtonPressed(views::Button* sender, 271 virtual void ButtonPressed(views::Button* sender,
153 const views::Event& event) OVERRIDE; 272 const views::Event& event) OVERRIDE;
154 273
155 virtual gfx::Size GetPreferredSize() OVERRIDE; 274 virtual gfx::Size GetPreferredSize() OVERRIDE;
156 275
157 protected: 276 protected:
158 virtual void OnEnabledChanged() OVERRIDE; 277 virtual void OnEnabledChanged() OVERRIDE;
159 278
160 private: 279 private:
(...skipping 26 matching lines...) Expand all
187 cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF, 306 cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, GridLayout::USE_PREF,
188 0, 0); 307 0, 0);
189 cs->AddPaddingColumn(1, 0); 308 cs->AddPaddingColumn(1, 0);
190 309
191 for (size_t i = 0; i < model_->GetInstalledServiceCount(); ++i) { 310 for (size_t i = 0; i < model_->GetInstalledServiceCount(); ++i) {
192 const WebIntentPickerModel::InstalledService& service = 311 const WebIntentPickerModel::InstalledService& service =
193 model_->GetInstalledServiceAt(i); 312 model_->GetInstalledServiceAt(i);
194 313
195 grid_layout->StartRow(0, 0); 314 grid_layout->StartRow(0, 0);
196 315
197 views::NativeTextButton* button = 316 ThrobberNativeTextButton* button =
198 new views::NativeTextButton(this, service.title); 317 new ThrobberNativeTextButton(this, service.title);
199 button->set_alignment(views::TextButton::ALIGN_LEFT); 318 button->set_alignment(views::TextButton::ALIGN_LEFT);
200 button->SetTooltipText(UTF8ToUTF16(service.url.spec().c_str())); 319 button->SetTooltipText(UTF8ToUTF16(service.url.spec().c_str()));
201 button->SetIcon(*service.favicon.ToSkBitmap()); 320 button->SetIcon(*service.favicon.ToSkBitmap());
202 button->set_tag(static_cast<int>(i)); 321 button->set_tag(static_cast<int>(i));
203 grid_layout->AddView(button); 322 grid_layout->AddView(button);
204 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 323 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
205 } 324 }
206 325
207 // Additional space to separate the buttons from the suggestions. 326 // Additional space to separate the buttons from the suggestions.
208 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 327 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
209 } 328 }
210 329
330 void ServiceButtonsView::StartThrobber(const GURL& url) {
331 for (size_t i = 0; i < model_->GetInstalledServiceCount(); ++i) {
332 const WebIntentPickerModel::InstalledService& service =
333 model_->GetInstalledServiceAt(i);
334 if (service.url != url)
335 continue;
336
337 ThrobberNativeTextButton* button =
338 static_cast<ThrobberNativeTextButton*>(child_at(i));
339 button->StartThrobber();
340 return;
341 }
342 }
343
211 void ServiceButtonsView::ButtonPressed(views::Button* sender, 344 void ServiceButtonsView::ButtonPressed(views::Button* sender,
212 const views::Event& event) { 345 const views::Event& event) {
213 size_t index = static_cast<size_t>(sender->tag()); 346 size_t index = static_cast<size_t>(sender->tag());
214 delegate_->OnServiceButtonClicked(model_->GetInstalledServiceAt(index)); 347 delegate_->OnServiceButtonClicked(model_->GetInstalledServiceAt(index));
215 } 348 }
216 349
217 gfx::Size ServiceButtonsView::GetPreferredSize() { 350 gfx::Size ServiceButtonsView::GetPreferredSize() {
218 // If there are no service buttons, hide this view. 351 // If there are no service buttons, hide this view.
219 if (model_->GetInstalledServiceCount() == 0) 352 if (model_->GetInstalledServiceCount() == 0)
220 return gfx::Size(); 353 return gfx::Size();
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
344 // A delegate to respond to button presses and clicked links. 477 // A delegate to respond to button presses and clicked links.
345 Delegate* delegate_; 478 Delegate* delegate_;
346 479
347 // The icon of the extension. 480 // The icon of the extension.
348 views::ImageView* icon_; 481 views::ImageView* icon_;
349 482
350 // The title of the extension, which links to the CWS detailed description of 483 // The title of the extension, which links to the CWS detailed description of
351 // this extension. 484 // this extension.
352 views::Link* title_link_; 485 views::Link* title_link_;
353 486
354 // A throbber to display when the extension is being installed.
355 views::Throbber* throbber_;
356
357 // The star rating of this extension. 487 // The star rating of this extension.
358 StarsView* stars_; 488 StarsView* stars_;
359 489
360 // A button to install the extension. 490 // A button to install the extension.
361 views::NativeTextButton* install_button_; 491 ThrobberNativeTextButton* install_button_;
362 492
363 DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsRowView); 493 DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsRowView);
364 }; 494 };
365 495
366 SuggestedExtensionsRowView::SuggestedExtensionsRowView( 496 SuggestedExtensionsRowView::SuggestedExtensionsRowView(
367 const WebIntentPickerModel::SuggestedExtension* extension, 497 const WebIntentPickerModel::SuggestedExtension* extension,
368 Delegate* delegate) 498 Delegate* delegate)
369 : extension_(extension), 499 : extension_(extension),
370 delegate_(delegate) { 500 delegate_(delegate) {
371 SetLayoutManager(new SuggestedExtensionsLayout); 501 SetLayoutManager(new SuggestedExtensionsLayout);
372 502
373 icon_ = new views::ImageView(); 503 icon_ = new views::ImageView();
374 icon_->SetImage(extension_->icon.ToSkBitmap()); 504 icon_->SetImage(extension_->icon.ToSkBitmap());
375 AddChildView(icon_); 505 AddChildView(icon_);
376 506
377 string16 elided_title = ui::ElideText( 507 string16 elided_title = ui::ElideText(
378 extension_->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END); 508 extension_->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END);
379 title_link_ = new views::Link(elided_title); 509 title_link_ = new views::Link(elided_title);
380 title_link_->set_listener(this); 510 title_link_->set_listener(this);
381 AddChildView(title_link_); 511 AddChildView(title_link_);
382 512
383 throbber_ = new views::Throbber(60, true);
384 throbber_->SetVisible(false);
385 AddChildView(throbber_);
386
387 stars_ = new StarsView(extension_->average_rating); 513 stars_ = new StarsView(extension_->average_rating);
388 AddChildView(stars_); 514 AddChildView(stars_);
389 515
390 install_button_= new views::NativeTextButton( 516 install_button_= new ThrobberNativeTextButton(
391 this, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION)); 517 this, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION));
392 AddChildView(install_button_); 518 AddChildView(install_button_);
393 } 519 }
394 520
395 SuggestedExtensionsRowView::~SuggestedExtensionsRowView() { 521 SuggestedExtensionsRowView::~SuggestedExtensionsRowView() {
396 } 522 }
397 523
398 void SuggestedExtensionsRowView::ButtonPressed(views::Button* sender, 524 void SuggestedExtensionsRowView::ButtonPressed(views::Button* sender,
399 const views::Event& event) { 525 const views::Event& event) {
400 delegate_->OnExtensionInstallClicked(extension_->id); 526 delegate_->OnExtensionInstallClicked(extension_->id);
401 } 527 }
402 528
403 void SuggestedExtensionsRowView::LinkClicked(views::Link* source, 529 void SuggestedExtensionsRowView::LinkClicked(views::Link* source,
404 int event_flags) { 530 int event_flags) {
405 delegate_->OnExtensionLinkClicked(extension_->id); 531 delegate_->OnExtensionLinkClicked(extension_->id);
406 } 532 }
407 533
408 void SuggestedExtensionsRowView::StartThrobber() { 534 void SuggestedExtensionsRowView::StartThrobber() {
409 stars_->SetVisible(false); 535 install_button_->StartThrobber();
410 install_button_->SetVisible(false); 536 install_button_->SetText(string16());
411 throbber_->SetVisible(true);
412 throbber_->Start();
413 Layout();
414 } 537 }
415 538
416 void SuggestedExtensionsRowView::StopThrobber() { 539 void SuggestedExtensionsRowView::StopThrobber() {
417 stars_->SetVisible(true); 540 install_button_->StopThrobber();
418 install_button_->SetVisible(true); 541 install_button_->SetText(
419 throbber_->SetVisible(false); 542 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION));
420 throbber_->Stop();
421 Layout();
422 } 543 }
423 544
424 void SuggestedExtensionsRowView::OnEnabledChanged() { 545 void SuggestedExtensionsRowView::OnEnabledChanged() {
425 title_link_->SetEnabled(enabled()); 546 title_link_->SetEnabled(enabled());
426 stars_->SetVisible(enabled()); 547 stars_->SetEnabled(enabled());
427 install_button_->SetVisible(enabled()); 548 install_button_->SetEnabled(enabled());
428 View::OnEnabledChanged(); 549 View::OnEnabledChanged();
429 Layout(); 550 Layout();
430 } 551 }
431 552
432 void SuggestedExtensionsRowView::PaintChildren(gfx::Canvas* canvas) { 553 void SuggestedExtensionsRowView::PaintChildren(gfx::Canvas* canvas) {
433 View::PaintChildren(canvas); 554 View::PaintChildren(canvas);
434 if (!enabled()) 555 if (!enabled())
435 canvas->FillRect(GetLocalBounds(), kHalfOpacityWhite); 556 canvas->FillRect(GetLocalBounds(), kHalfOpacityWhite);
436 } 557 }
437 558
438 // SuggestedExtensionsView ----------------------------------------------------- 559 // SuggestedExtensionsView -----------------------------------------------------
439 560
440 // A view that contains suggested extensions from the Chrome Web Store that 561 // A view that contains suggested extensions from the Chrome Web Store that
441 // provide an intent service matching the action/type pair. 562 // provide an intent service matching the action/type pair.
442 // This view also displays the "More suggestions" link which searches the
443 // Chrome Web Store for more extensions.
444 class SuggestedExtensionsView : public views::View { 563 class SuggestedExtensionsView : public views::View {
445 public: 564 public:
446 SuggestedExtensionsView(const WebIntentPickerModel* model, 565 SuggestedExtensionsView(const WebIntentPickerModel* model,
447 SuggestedExtensionsRowView::Delegate* delegate); 566 SuggestedExtensionsRowView::Delegate* delegate);
448 567
449 virtual ~SuggestedExtensionsView(); 568 virtual ~SuggestedExtensionsView();
450 569
451 void Clear(); 570 void Clear();
452 571
453 // Update the view to the new model data. 572 // Update the view to the new model data.
454 void Update(); 573 void Update();
455 574
456 // Show the install throbber for the row containing |extension_id|. This 575 // Show the install throbber for the row containing |extension_id|. This
457 // function also hides hides and disables other buttons and links. 576 // function also hides hides and disables other buttons and links.
458 void StartThrobber(const string16& extension_id); 577 void StartThrobber(const string16& extension_id);
459 578
460 // Hide the install throbber. This function re-enables all buttons and links. 579 // Hide the install throbber. This function re-enables all buttons and links.
461 void StopThrobber(); 580 void StopThrobber();
462 581
582 protected:
583 virtual void OnEnabledChanged() OVERRIDE;
584
463 private: 585 private:
464 const WebIntentPickerModel* model_; 586 const WebIntentPickerModel* model_;
465 SuggestedExtensionsRowView::Delegate* delegate_; 587 SuggestedExtensionsRowView::Delegate* delegate_;
466 588
467 DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsView); 589 DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsView);
468 }; 590 };
469 591
470 SuggestedExtensionsView::SuggestedExtensionsView( 592 SuggestedExtensionsView::SuggestedExtensionsView(
471 const WebIntentPickerModel* model, 593 const WebIntentPickerModel* model,
472 SuggestedExtensionsRowView::Delegate* delegate) 594 SuggestedExtensionsRowView::Delegate* delegate)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 633
512 void SuggestedExtensionsView::StopThrobber() { 634 void SuggestedExtensionsView::StopThrobber() {
513 for (size_t i = 0; i < model_->GetSuggestedExtensionCount(); ++i) { 635 for (size_t i = 0; i < model_->GetSuggestedExtensionCount(); ++i) {
514 SuggestedExtensionsRowView* row = 636 SuggestedExtensionsRowView* row =
515 static_cast<SuggestedExtensionsRowView*>(child_at(i)); 637 static_cast<SuggestedExtensionsRowView*>(child_at(i));
516 row->SetEnabled(true); 638 row->SetEnabled(true);
517 row->StopThrobber(); 639 row->StopThrobber();
518 } 640 }
519 } 641 }
520 642
643 void SuggestedExtensionsView::OnEnabledChanged() {
644 EnableChildViews(this, enabled());
645 View::OnEnabledChanged();
646 }
647
521 } // namespace 648 } // namespace
522 649
523 // WebIntentPickerViews -------------------------------------------------------- 650 // WebIntentPickerViews --------------------------------------------------------
524 651
525 // Views implementation of WebIntentPicker. 652 // Views implementation of WebIntentPicker.
526 class WebIntentPickerViews : public views::ButtonListener, 653 class WebIntentPickerViews : public views::ButtonListener,
527 public views::DialogDelegate, 654 public views::DialogDelegate,
528 public views::LinkListener, 655 public views::LinkListener,
529 public WebIntentPicker, 656 public WebIntentPicker,
530 public WebIntentPickerModelObserver, 657 public WebIntentPickerModelObserver,
(...skipping 19 matching lines...) Expand all
550 virtual int GetDialogButtons() const OVERRIDE; 677 virtual int GetDialogButtons() const OVERRIDE;
551 678
552 // LinkListener implementation. 679 // LinkListener implementation.
553 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 680 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
554 681
555 // WebIntentPicker implementation. 682 // WebIntentPicker implementation.
556 virtual void Close() OVERRIDE; 683 virtual void Close() OVERRIDE;
557 virtual void SetActionString(const string16& action) OVERRIDE; 684 virtual void SetActionString(const string16& action) OVERRIDE;
558 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; 685 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
559 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE; 686 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE;
687 virtual void OnInlineDispositionWebContentsLoaded(
688 content::WebContents* web_contents) OVERRIDE;
560 689
561 // WebIntentPickerModelObserver implementation. 690 // WebIntentPickerModelObserver implementation.
562 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE; 691 virtual void OnModelChanged(WebIntentPickerModel* model) OVERRIDE;
563 virtual void OnFaviconChanged(WebIntentPickerModel* model, 692 virtual void OnFaviconChanged(WebIntentPickerModel* model,
564 size_t index) OVERRIDE; 693 size_t index) OVERRIDE;
565 virtual void OnExtensionIconChanged(WebIntentPickerModel* model, 694 virtual void OnExtensionIconChanged(WebIntentPickerModel* model,
566 const string16& extension_id) OVERRIDE; 695 const string16& extension_id) OVERRIDE;
567 virtual void OnInlineDisposition(WebIntentPickerModel* model, 696 virtual void OnInlineDisposition(WebIntentPickerModel* model,
568 const GURL& url) OVERRIDE; 697 const GURL& url) OVERRIDE;
569 698
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 747
619 // A weak pointer to the constrained window. 748 // A weak pointer to the constrained window.
620 ConstrainedWindowViews* window_; 749 ConstrainedWindowViews* window_;
621 750
622 // A weak pointer to the more suggestions link. 751 // A weak pointer to the more suggestions link.
623 views::Link* more_suggestions_link_; 752 views::Link* more_suggestions_link_;
624 753
625 // A weak pointer to the choose another service link. 754 // A weak pointer to the choose another service link.
626 views::Link* choose_another_service_link_; 755 views::Link* choose_another_service_link_;
627 756
757 // Set to true when displaying the inline disposition web contents. Used to
758 // prevent laying out the inline disposition widgets twice.
759 bool displaying_web_contents_;
760
628 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews); 761 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews);
629 }; 762 };
630 763
631 // static 764 // static
632 WebIntentPicker* WebIntentPicker::Create(Browser* browser, 765 WebIntentPicker* WebIntentPicker::Create(Browser* browser,
633 TabContentsWrapper* wrapper, 766 TabContentsWrapper* wrapper,
634 WebIntentPickerDelegate* delegate, 767 WebIntentPickerDelegate* delegate,
635 WebIntentPickerModel* model) { 768 WebIntentPickerModel* model) {
636 WebIntentPickerViews* picker = 769 WebIntentPickerViews* picker =
637 new WebIntentPickerViews(browser, wrapper, delegate, model); 770 new WebIntentPickerViews(browser, wrapper, delegate, model);
638 771
639 return picker; 772 return picker;
640 } 773 }
641 774
642 WebIntentPickerViews::WebIntentPickerViews(Browser* browser, 775 WebIntentPickerViews::WebIntentPickerViews(Browser* browser,
643 TabContentsWrapper* wrapper, 776 TabContentsWrapper* wrapper,
644 WebIntentPickerDelegate* delegate, 777 WebIntentPickerDelegate* delegate,
645 WebIntentPickerModel* model) 778 WebIntentPickerModel* model)
646 : delegate_(delegate), 779 : delegate_(delegate),
647 model_(model), 780 model_(model),
648 service_buttons_(NULL), 781 service_buttons_(NULL),
649 action_label_(NULL), 782 action_label_(NULL),
650 suggestions_label_(NULL), 783 suggestions_label_(NULL),
651 extensions_(NULL), 784 extensions_(NULL),
652 browser_(browser), 785 browser_(browser),
653 contents_(NULL), 786 contents_(NULL),
654 window_(NULL), 787 window_(NULL),
655 more_suggestions_link_(NULL), 788 more_suggestions_link_(NULL),
656 choose_another_service_link_(NULL) { 789 choose_another_service_link_(NULL),
790 displaying_web_contents_(false) {
657 model_->set_observer(this); 791 model_->set_observer(this);
658 InitContents(); 792 InitContents();
659 793
660 // Show the dialog. 794 // Show the dialog.
661 window_ = new ConstrainedWindowViews(wrapper, this); 795 window_ = new ConstrainedWindowViews(wrapper, this);
662 } 796 }
663 797
664 WebIntentPickerViews::~WebIntentPickerViews() { 798 WebIntentPickerViews::~WebIntentPickerViews() {
665 model_->set_observer(NULL); 799 model_->set_observer(NULL);
666 } 800 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 860
727 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) { 861 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) {
728 service_buttons_->SetEnabled(true); 862 service_buttons_->SetEnabled(true);
729 extensions_->StopThrobber(); 863 extensions_->StopThrobber();
730 more_suggestions_link_->SetEnabled(true); 864 more_suggestions_link_->SetEnabled(true);
731 contents_->Layout(); 865 contents_->Layout();
732 866
733 // TODO(binji): What to display to user on failure? 867 // TODO(binji): What to display to user on failure?
734 } 868 }
735 869
736 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) { 870 void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded(
737 if (model->GetInstalledServiceCount() == 0) { 871 content::WebContents* web_contents) {
738 suggestions_label_->SetText(l10n_util::GetStringUTF16( 872 if (displaying_web_contents_)
739 IDS_INTENT_PICKER_GET_MORE_SERVICES_NONE_INSTALLED)); 873 return;
740 } else {
741 suggestions_label_->SetText(
742 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_GET_MORE_SERVICES));
743 }
744
745 service_buttons_->Update();
746 extensions_->Update();
747 contents_->Layout();
748 SizeToContents();
749 }
750
751 void WebIntentPickerViews::OnFaviconChanged(
752 WebIntentPickerModel* model, size_t index) {
753 service_buttons_->Update();
754 contents_->Layout();
755 SizeToContents();
756 }
757
758 void WebIntentPickerViews::OnExtensionIconChanged(
759 WebIntentPickerModel* model,
760 const string16& extension_id) {
761 extensions_->Update();
762 contents_->Layout();
763 SizeToContents();
764 }
765
766 void WebIntentPickerViews::OnInlineDisposition(
767 WebIntentPickerModel* model, const GURL& url) {
768 WebContents* web_contents = WebContents::Create(
769 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
770 inline_disposition_delegate_.reset(new WebIntentInlineDispositionDelegate);
771 web_contents->SetDelegate(inline_disposition_delegate_.get());
772
773 const WebIntentPickerModel::InstalledService* service =
774 model->GetInstalledServiceWithURL(url);
775 DCHECK(service);
776
777 // Must call this immediately after WebContents creation to avoid race
778 // with load.
779 delegate_->OnInlineDispositionWebContentsCreated(web_contents);
780
781 TabContentsContainer* tab_contents_container = new TabContentsContainer;
782
783 web_contents->GetController().LoadURL(
784 url,
785 content::Referrer(),
786 content::PAGE_TRANSITION_START_PAGE,
787 std::string());
788 874
789 // Replace the picker with the inline disposition. 875 // Replace the picker with the inline disposition.
790 contents_->RemoveAllChildViews(true); 876 contents_->RemoveAllChildViews(true);
791 877
792 views::GridLayout* grid_layout = new views::GridLayout(contents_); 878 views::GridLayout* grid_layout = new views::GridLayout(contents_);
793 contents_->SetLayoutManager(grid_layout); 879 contents_->SetLayoutManager(grid_layout);
794 880
795 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder, 881 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
796 kContentAreaBorder, kContentAreaBorder); 882 kContentAreaBorder, kContentAreaBorder);
797 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0); 883 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
798 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 884 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
799 GridLayout::USE_PREF, 0, 0); // Icon. 885 GridLayout::USE_PREF, 0, 0); // Icon.
800 header_cs->AddPaddingColumn(0, 4); 886 header_cs->AddPaddingColumn(0, 4);
801 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 887 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
802 GridLayout::USE_PREF, 0, 0); // Title. 888 GridLayout::USE_PREF, 0, 0); // Title.
803 header_cs->AddPaddingColumn(0, 4); 889 header_cs->AddPaddingColumn(0, 4);
804 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 890 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
805 GridLayout::USE_PREF, 0, 0); // Link. 891 GridLayout::USE_PREF, 0, 0); // Link.
806 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing); 892 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
807 #if defined(USE_CLOSE_BUTTON) 893 #if defined(USE_CLOSE_BUTTON)
808 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 894 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
809 GridLayout::USE_PREF, 0, 0); // Close Button. 895 GridLayout::USE_PREF, 0, 0); // Close Button.
810 #endif 896 #endif
811 897
812 views::ColumnSet* full_cs = grid_layout->AddColumnSet(1); 898 views::ColumnSet* full_cs = grid_layout->AddColumnSet(1);
813 full_cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, 899 full_cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
814 GridLayout::USE_PREF, 0, 0); 900 GridLayout::USE_PREF, 0, 0);
815 901
902 const WebIntentPickerModel::InstalledService* service =
903 model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
904
816 // Header row. 905 // Header row.
817 grid_layout->StartRow(0, 0); 906 grid_layout->StartRow(0, 0);
818 views::ImageView* icon = new views::ImageView(); 907 views::ImageView* icon = new views::ImageView();
819 icon->SetImage(service->favicon.ToSkBitmap()); 908 icon->SetImage(service->favicon.ToSkBitmap());
820 grid_layout->AddView(icon); 909 grid_layout->AddView(icon);
821 910
822 string16 elided_title = ui::ElideText( 911 string16 elided_title = ui::ElideText(
823 service->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END); 912 service->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END);
824 views::Label* title = new views::Label(elided_title); 913 views::Label* title = new views::Label(elided_title);
825 grid_layout->AddView(title); 914 grid_layout->AddView(title);
826 915
827 choose_another_service_link_ = new views::Link( 916 choose_another_service_link_ = new views::Link(
828 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE)); 917 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
829 grid_layout->AddView(choose_another_service_link_); 918 grid_layout->AddView(choose_another_service_link_);
830 919
831 #if defined(USE_CLOSE_BUTTON) 920 #if defined(USE_CLOSE_BUTTON)
832 grid_layout->AddView(CreateCloseButton()); 921 grid_layout->AddView(CreateCloseButton());
833 #endif 922 #endif
834 923
835 // Inline web contents row. 924 // Inline web contents row.
836 grid_layout->StartRow(0, 1); 925 grid_layout->StartRow(0, 1);
926 TabContentsContainer* tab_contents_container = new TabContentsContainer;
837 grid_layout->AddView(tab_contents_container, 1, 1, GridLayout::CENTER, 927 grid_layout->AddView(tab_contents_container, 1, 1, GridLayout::CENTER,
838 GridLayout::CENTER, kDialogMinWidth, 140); 928 GridLayout::CENTER, kDialogMinWidth, 140);
839 929
840 // The contents can only be changed after the child is added to view 930 // The contents can only be changed after the child is added to view
841 // hierarchy. 931 // hierarchy.
842 tab_contents_container->ChangeWebContents(web_contents); 932 tab_contents_container->ChangeWebContents(web_contents);
843
844 contents_->Layout(); 933 contents_->Layout();
845 SizeToContents(); 934 SizeToContents();
935 displaying_web_contents_ = true;
936 }
937
938 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
939 if (model->GetInstalledServiceCount() == 0) {
940 suggestions_label_->SetText(l10n_util::GetStringUTF16(
941 IDS_INTENT_PICKER_GET_MORE_SERVICES_NONE_INSTALLED));
942 } else {
943 suggestions_label_->SetText(
944 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_GET_MORE_SERVICES));
945 }
946
947 service_buttons_->Update();
948 extensions_->Update();
949 contents_->Layout();
950 SizeToContents();
951 }
952
953 void WebIntentPickerViews::OnFaviconChanged(
954 WebIntentPickerModel* model, size_t index) {
955 service_buttons_->Update();
956 contents_->Layout();
957 SizeToContents();
958 }
959
960 void WebIntentPickerViews::OnExtensionIconChanged(
961 WebIntentPickerModel* model,
962 const string16& extension_id) {
963 extensions_->Update();
964 contents_->Layout();
965 SizeToContents();
966 }
967
968 void WebIntentPickerViews::OnInlineDisposition(
969 WebIntentPickerModel* model, const GURL& url) {
970 WebContents* web_contents = WebContents::Create(
971 browser_->profile(), NULL, MSG_ROUTING_NONE, NULL, NULL);
972 inline_disposition_delegate_.reset(
973 new WebIntentInlineDispositionDelegate(this));
974 web_contents->SetDelegate(inline_disposition_delegate_.get());
975
976 const WebIntentPickerModel::InstalledService* service =
977 model->GetInstalledServiceWithURL(url);
978 DCHECK(service);
979
980 // Must call this immediately after WebContents creation to avoid race
981 // with load.
982 delegate_->OnInlineDispositionWebContentsCreated(web_contents);
983 web_contents->GetController().LoadURL(
984 url,
985 content::Referrer(),
986 content::PAGE_TRANSITION_START_PAGE,
987 std::string());
988
989 // Disable all buttons and show throbber.
990 service_buttons_->SetEnabled(false);
991 service_buttons_->StartThrobber(url);
992 extensions_->SetEnabled(false);
993 more_suggestions_link_->SetEnabled(false);
994 contents_->Layout();
846 } 995 }
847 996
848 void WebIntentPickerViews::OnServiceButtonClicked( 997 void WebIntentPickerViews::OnServiceButtonClicked(
849 const WebIntentPickerModel::InstalledService& service) { 998 const WebIntentPickerModel::InstalledService& service) {
850 delegate_->OnServiceChosen(service.url, service.disposition); 999 delegate_->OnServiceChosen(service.url, service.disposition);
851 } 1000 }
852 1001
853 void WebIntentPickerViews::OnExtensionInstallClicked( 1002 void WebIntentPickerViews::OnExtensionInstallClicked(
854 const string16& extension_id) { 1003 const string16& extension_id) {
855 service_buttons_->SetEnabled(false); 1004 service_buttons_->SetEnabled(false);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
966 views::ImageButton* close_button = new views::ImageButton(this); 1115 views::ImageButton* close_button = new views::ImageButton(this);
967 close_button->SetImage(views::CustomButton::BS_NORMAL, 1116 close_button->SetImage(views::CustomButton::BS_NORMAL,
968 rb.GetBitmapNamed(IDR_CLOSE_BAR)); 1117 rb.GetBitmapNamed(IDR_CLOSE_BAR));
969 close_button->SetImage(views::CustomButton::BS_HOT, 1118 close_button->SetImage(views::CustomButton::BS_HOT,
970 rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); 1119 rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
971 close_button->SetImage(views::CustomButton::BS_PUSHED, 1120 close_button->SetImage(views::CustomButton::BS_PUSHED,
972 rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); 1121 rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
973 return close_button; 1122 return close_button;
974 } 1123 }
975 #endif 1124 #endif
OLDNEW
« no previous file with comments | « chrome/browser/ui/intents/web_intent_picker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698