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

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