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

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

Issue 11192014: Revert 162252 - Make Web Intents picker in Views conform to latest mocks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 2 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/views/tab_modal_confirm_dialog_views.cc ('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/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
9 #include "base/time.h" 9 #include "base/time.h"
10 #include "base/timer.h"
11 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/download/download_util.h"
13 #include "chrome/browser/tab_contents/tab_util.h" 11 #include "chrome/browser/tab_contents/tab_util.h"
14 #include "chrome/browser/ui/browser_finder.h" 12 #include "chrome/browser/ui/browser_finder.h"
15 #include "chrome/browser/ui/browser_navigator.h" 13 #include "chrome/browser/ui/browser_navigator.h"
16 #include "chrome/browser/ui/constrained_window_constants.h"
17 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h" 14 #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h"
18 #include "chrome/browser/ui/intents/web_intent_picker.h" 15 #include "chrome/browser/ui/intents/web_intent_picker.h"
19 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h" 16 #include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
20 #include "chrome/browser/ui/intents/web_intent_picker_model.h" 17 #include "chrome/browser/ui/intents/web_intent_picker_model.h"
21 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h" 18 #include "chrome/browser/ui/intents/web_intent_picker_model_observer.h"
22 #include "chrome/browser/ui/tab_contents/tab_contents.h" 19 #include "chrome/browser/ui/tab_contents/tab_contents.h"
23 #include "chrome/browser/ui/views/constrained_window_views.h" 20 #include "chrome/browser/ui/views/constrained_window_views.h"
24 #include "chrome/browser/ui/views/frame/browser_view.h" 21 #include "chrome/browser/ui/views/frame/browser_view.h"
25 #include "chrome/browser/ui/views/location_bar/location_icon_view.h" 22 #include "chrome/browser/ui/views/location_bar/location_icon_view.h"
26 #include "chrome/browser/ui/views/toolbar_view.h" 23 #include "chrome/browser/ui/views/toolbar_view.h"
(...skipping 15 matching lines...) Expand all
42 #include "ui/gfx/canvas.h" 39 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/image/image.h" 40 #include "ui/gfx/image/image.h"
44 #include "ui/gfx/image/image_skia_operations.h" 41 #include "ui/gfx/image/image_skia_operations.h"
45 #include "ui/views/border.h" 42 #include "ui/views/border.h"
46 #include "ui/views/controls/button/image_button.h" 43 #include "ui/views/controls/button/image_button.h"
47 #include "ui/views/controls/button/text_button.h" 44 #include "ui/views/controls/button/text_button.h"
48 #include "ui/views/controls/image_view.h" 45 #include "ui/views/controls/image_view.h"
49 #include "ui/views/controls/label.h" 46 #include "ui/views/controls/label.h"
50 #include "ui/views/controls/link.h" 47 #include "ui/views/controls/link.h"
51 #include "ui/views/controls/link_listener.h" 48 #include "ui/views/controls/link_listener.h"
52 #include "ui/views/controls/separator.h"
53 #include "ui/views/controls/throbber.h" 49 #include "ui/views/controls/throbber.h"
54 #include "ui/views/controls/webview/webview.h" 50 #include "ui/views/controls/webview/webview.h"
55 #include "ui/views/layout/box_layout.h" 51 #include "ui/views/layout/box_layout.h"
56 #include "ui/views/layout/fill_layout.h" 52 #include "ui/views/layout/fill_layout.h"
57 #include "ui/views/layout/grid_layout.h" 53 #include "ui/views/layout/grid_layout.h"
58 #include "ui/views/layout/layout_constants.h" 54 #include "ui/views/layout/layout_constants.h"
59 #include "ui/views/view.h" 55 #include "ui/views/view.h"
60 #include "ui/views/widget/widget.h" 56 #include "ui/views/widget/widget.h"
61 #include "ui/views/window/dialog_delegate.h" 57 #include "ui/views/window/dialog_delegate.h"
62 #include "ui/views/window/non_client_view.h" 58 #include "ui/views/window/non_client_view.h"
63 59
64 using content::WebContents; 60 using content::WebContents;
65 using views::GridLayout; 61 using views::GridLayout;
66 62
67 namespace { 63 namespace {
68 64
69 // The color used to dim disabled elements. 65 // The color used to dim disabled elements.
70 const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255); 66 const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255);
71 67
72 // The color used to display an enabled label.
73 const SkColor kEnabledLabelColor = SkColorSetRGB(51, 51, 51);
74
75 // The color used to display an enabled link.
76 const SkColor kEnabledLinkColor = SkColorSetRGB(17, 85, 204);
77
78 // The color used to display a disabled link. 68 // The color used to display a disabled link.
79 const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128); 69 const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128);
80 70
81 // The time between successive throbber frames in milliseconds. 71 // The time between successive throbber frames in milliseconds.
82 const int kThrobberFrameTimeMs = 50; 72 const int kThrobberFrameTimeMs = 50;
83 73
84 // Width of IntentView action button in pixels 74 // Width of IntentView action button in pixels
85 const int kButtonWidth = 130; 75 const int kButtonWidth = 130;
86 76
87 // Minimum number of action buttons - fill up with suggestions as needed. 77 // Minimum number of action buttons - fill up with suggestions as needed.
88 const int kMinRowCount = 4; 78 const int kMinRowCount = 4;
89 79
90 // Maximum number of action buttons - do not add suggestions to reach. 80 // Maximum number of action buttons - do not add suggestions to reach.
91 const int kMaxRowCount = 8; 81 const int kMaxRowCount = 8;
92 82
93 // The vertical padding around the UI elements in the waiting view.
94 const int kWaitingViewVerticalPadding = 40;
95
96 // Enables or disables all child views of |view|. 83 // Enables or disables all child views of |view|.
97 void EnableChildViews(views::View* view, bool enabled) { 84 void EnableChildViews(views::View* view, bool enabled) {
98 for (int i = 0; i < view->child_count(); ++i) { 85 for (int i = 0; i < view->child_count(); ++i) {
99 views::View* child = view->child_at(i); 86 views::View* child = view->child_at(i);
100 child->SetEnabled(enabled); 87 child->SetEnabled(enabled);
101 } 88 }
102 } 89 }
103 90
104 // Create a "close" button. 91 // Create a "close" button.
105 views::ImageButton* CreateCloseButton(views::ButtonListener* listener) { 92 views::ImageButton* CreateCloseButton(views::ButtonListener* listener) {
106 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 93 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
107 views::ImageButton* close_button = new views::ImageButton(listener); 94 views::ImageButton* close_button = new views::ImageButton(listener);
108 close_button->SetImage(views::CustomButton::BS_NORMAL, 95 close_button->SetImage(views::CustomButton::BS_NORMAL,
109 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X)); 96 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X));
110 close_button->SetImage(views::CustomButton::BS_HOT, 97 close_button->SetImage(views::CustomButton::BS_HOT,
111 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X_HOVER)); 98 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X_HOVER));
112 close_button->SetImage(views::CustomButton::BS_PUSHED, 99 close_button->SetImage(views::CustomButton::BS_PUSHED,
113 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X_HOVER)); 100 rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X_HOVER));
114 return close_button; 101 return close_button;
115 } 102 }
116 103 // SarsView -------------------------------------------------------------------
117 // Creates a label.
118 views::Label* CreateLabel() {
119 views::Label* label = new views::Label();
120 label->SetEnabledColor(kEnabledLabelColor);
121 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
122 return label;
123 }
124
125 // Creates a title-style label.
126 views::Label* CreateTitleLabel() {
127 views::Label* label = CreateLabel();
128 label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
129 ui::ResourceBundle::MediumFont));
130 const int kLabelBuiltinTopPadding = 5;
131 label->set_border(views::Border::CreateEmptyBorder(
132 WebIntentPicker::kContentAreaBorder -
133 ConstrainedWindowConstants::kCloseButtonPadding -
134 kLabelBuiltinTopPadding,
135 0, 0, 0));
136 return label;
137 }
138
139 // Creates a link.
140 views::Link* CreateLink() {
141 views::Link* link = new views::Link();
142 link->SetEnabledColor(kEnabledLinkColor);
143 link->SetDisabledColor(kDisabledLinkColor);
144 link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
145 return link;
146 }
147
148 // Creates a header for the inline disposition dialog.
149 views::View* CreateInlineDispositionHeader(
150 views::ImageView* app_icon,
151 views::Label* app_title,
152 views::Link* use_another_service_link) {
153 views::View* header = new views::View();
154 views::GridLayout* grid_layout = new views::GridLayout(header);
155 const int kIconBuiltinTopPadding = 6;
156 grid_layout->SetInsets(
157 WebIntentPicker::kContentAreaBorder -
158 ConstrainedWindowConstants::kCloseButtonPadding -
159 kIconBuiltinTopPadding,
160 0, 0, 0);
161 header->SetLayoutManager(grid_layout);
162 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
163 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
164 GridLayout::USE_PREF, 0, 0); // App icon.
165 header_cs->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
166 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
167 GridLayout::USE_PREF, 0, 0); // App title.
168 header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
169 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
170 GridLayout::USE_PREF, 0, 0); // Use another app link.
171 grid_layout->StartRow(0, 0);
172 grid_layout->AddView(app_icon);
173 grid_layout->AddView(app_title);
174 grid_layout->AddView(use_another_service_link);
175 header->Layout();
176 return header;
177 }
178
179 // Checks whether the inline disposition dialog should show the link for using
180 // another service.
181 bool IsUseAnotherServiceVisible(WebIntentPickerModel* model) {
182 DCHECK(model);
183 return model->show_use_another_service() &&
184 (model->GetInstalledServiceCount() > 1 ||
185 model->GetSuggestedExtensionCount());
186 }
187
188
189 // StarsView -------------------------------------------------------------------
190 104
191 // A view that displays 5 stars: empty, full or half full, given a rating in 105 // A view that displays 5 stars: empty, full or half full, given a rating in
192 // the range [0,5]. 106 // the range [0,5].
193 class StarsView : public views::View { 107 class StarsView : public views::View {
194 public: 108 public:
195 explicit StarsView(double rating); 109 explicit StarsView(double rating);
196 virtual ~StarsView(); 110 virtual ~StarsView();
197 111
198 private: 112 private:
199 // The star rating to display, in the range [0,5]. 113 // The star rating to display, in the range [0,5].
(...skipping 20 matching lines...) Expand all
220 // TODO(binji): Add tooltip with text rating 134 // TODO(binji): Add tooltip with text rating
221 // "Average Rating: X.XX stars (YYYYY)" 135 // "Average Rating: X.XX stars (YYYYY)"
222 // Y = "1: Hated it, 2: Disliked it, 3: It was okay, 4: Liked it, 136 // Y = "1: Hated it, 2: Disliked it, 3: It was okay, 4: Liked it,
223 // 5: Loved it" 137 // 5: Loved it"
224 // Choose Y based on rounded X. 138 // Choose Y based on rounded X.
225 } 139 }
226 140
227 StarsView::~StarsView() { 141 StarsView::~StarsView() {
228 } 142 }
229 143
230
231 // ThrobberNativeTextButton ---------------------------------------------------- 144 // ThrobberNativeTextButton ----------------------------------------------------
232 145
233 // A native text button that can display a throbber in place of its icon. Much 146 // A native text button that can display a throbber in place of its icon. Much
234 // of the logic of this class is copied from ui/views/controls/throbber.h. 147 // of the logic of this class is copied from ui/views/controls/throbber.h.
235 class ThrobberNativeTextButton : public views::NativeTextButton { 148 class ThrobberNativeTextButton : public views::NativeTextButton {
236 public: 149 public:
237 ThrobberNativeTextButton(views::ButtonListener* listener, 150 ThrobberNativeTextButton(views::ButtonListener* listener,
238 const string16& text); 151 const string16& text);
239 virtual ~ThrobberNativeTextButton(); 152 virtual ~ThrobberNativeTextButton();
240 153
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 this_frame_ = gfx::ImageSkiaOperations::ExtractSubset(*frames_, subset_rect); 261 this_frame_ = gfx::ImageSkiaOperations::ExtractSubset(*frames_, subset_rect);
349 return this_frame_; 262 return this_frame_;
350 } 263 }
351 264
352 void ThrobberNativeTextButton::Run() { 265 void ThrobberNativeTextButton::Run() {
353 DCHECK(running_); 266 DCHECK(running_);
354 267
355 SchedulePaint(); 268 SchedulePaint();
356 } 269 }
357 270
358
359 // SpinnerProgressIndicator ----------------------------------------------------
360 class SpinnerProgressIndicator : public views::View {
361 public:
362 SpinnerProgressIndicator();
363 virtual ~SpinnerProgressIndicator();
364
365 void SetPercentDone(int percent);
366 void SetIndeterminate(bool indetereminate);
367
368 // Overridden from views::View.
369 virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
370 virtual gfx::Size GetPreferredSize() OVERRIDE;
371
372 private:
373 void UpdateTimer();
374 int GetProgressAngle();
375
376 static const int kTimerIntervalMs = 1000 / 30;
377 static const int kSpinRateDegreesPerSecond = 270;
378
379 int percent_done_;
380 int indeterminate_;
381
382 base::TimeTicks start_time_;
383 base::RepeatingTimer<SpinnerProgressIndicator> timer_;
384
385 DISALLOW_COPY_AND_ASSIGN(SpinnerProgressIndicator);
386 };
387
388 SpinnerProgressIndicator::SpinnerProgressIndicator()
389 : percent_done_(0),
390 indeterminate_(true) {}
391
392 SpinnerProgressIndicator::~SpinnerProgressIndicator() {
393 }
394
395 void SpinnerProgressIndicator::SetPercentDone(int percent) {
396 percent_done_ = percent;
397 SchedulePaint();
398 UpdateTimer();
399 }
400
401 void SpinnerProgressIndicator::SetIndeterminate(bool indetereminate) {
402 indeterminate_ = indetereminate;
403 SchedulePaint();
404 UpdateTimer();
405 }
406
407 void SpinnerProgressIndicator::Paint(gfx::Canvas* canvas) {
408 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
409 gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
410 gfx::ImageSkia* bg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_BACKGROUND);
411 download_util::PaintCustomDownloadProgress(
412 canvas,
413 *bg,
414 *fg,
415 fg->width(),
416 bounds(),
417 GetProgressAngle(),
418 indeterminate_ ? -1 : percent_done_);
419 }
420
421 gfx::Size SpinnerProgressIndicator::GetPreferredSize() {
422 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
423 gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
424 return fg->size();
425 }
426
427 void SpinnerProgressIndicator::UpdateTimer() {
428 if (!parent() || !indeterminate_) {
429 timer_.Stop();
430 return;
431 }
432
433 if (!timer_.IsRunning()) {
434 start_time_ = base::TimeTicks::Now();
435 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimerIntervalMs),
436 this, &SpinnerProgressIndicator::SchedulePaint);
437 }
438 }
439
440 int SpinnerProgressIndicator::GetProgressAngle() {
441 if (!indeterminate_)
442 return download_util::kStartAngleDegrees;
443 base::TimeDelta delta = base::TimeTicks::Now() - start_time_;
444 int angle = delta.InSecondsF() * kSpinRateDegreesPerSecond;
445 return angle % 360;
446 }
447
448
449 // WaitingView ---------------------------------------------------------- 271 // WaitingView ----------------------------------------------------------
450 class WaitingView : public views::View { 272 class WaitingView : public views::View {
451 public: 273 public:
452 WaitingView(views::ButtonListener* listener, bool use_close_button); 274 WaitingView(views::ButtonListener* listener, bool use_close_button);
453 virtual ~WaitingView();
454 275
455 private: 276 private:
456 DISALLOW_COPY_AND_ASSIGN(WaitingView); 277 DISALLOW_COPY_AND_ASSIGN(WaitingView);
457 }; 278 };
458 279
459 WaitingView::WaitingView(views::ButtonListener* listener, 280 WaitingView::WaitingView(views::ButtonListener* listener,
460 bool use_close_button) { 281 bool use_close_button) {
461 views::GridLayout* layout = new views::GridLayout(this); 282 views::GridLayout* layout = new views::GridLayout(this);
462 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0)); 283 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
463 const int kMessageBuiltinBottomPadding = 3; 284 layout->SetInsets(WebIntentPicker::kContentAreaBorder,
464 layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 285 WebIntentPicker::kContentAreaBorder,
465 0, 286 WebIntentPicker::kContentAreaBorder,
466 kWaitingViewVerticalPadding - kMessageBuiltinBottomPadding, 287 WebIntentPicker::kContentAreaBorder);
467 0);
468 SetLayoutManager(layout); 288 SetLayoutManager(layout);
469 289
470 enum GridLayoutColumnSets { 290 views::ColumnSet* cs = layout->AddColumnSet(0);
471 HEADER_ROW, 291 views::ColumnSet* header_cs = NULL;
472 CONTENT_ROW, 292 if (use_close_button) {
473 }; 293 header_cs = layout->AddColumnSet(1);
474 views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW); 294 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
475 header_cs->AddPaddingColumn(1, 1); 295 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
476 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0, 296 GridLayout::USE_PREF, 0, 0); // Close Button.
477 GridLayout::USE_PREF, 0, 0); 297 }
478 header_cs->AddPaddingColumn( 298 cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
479 0, ConstrainedWindowConstants::kCloseButtonPadding); 299 cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER,
300 1, GridLayout::USE_PREF, 0, 0);
301 cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
480 302
481 views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW); 303 // Create throbber.
482 content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation); 304 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
483 content_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1, 305 const gfx::ImageSkia* frames =
484 GridLayout::USE_PREF, 0, 0); 306 rb.GetImageNamed(IDR_SPEECH_INPUT_SPINNER).ToImageSkia();
485 content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation); 307 views::Throbber* throbber = new views::Throbber(kThrobberFrameTimeMs, true);
308 throbber->SetFrames(frames);
309 throbber->Start();
486 310
487 // Close button 311 // Create text.
488 layout->StartRow(0, HEADER_ROW); 312 views::Label* label = new views::Label();
489 views::ImageButton* close_button = CreateCloseButton(listener); 313 label->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
490 layout->AddView(close_button); 314 label->SetFont(rb.GetFont(ui::ResourceBundle::MediumBoldFont));
491 close_button->SetVisible(use_close_button); 315 label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
492 316
493 // Throbber 317 // Layout the view.
494 layout->AddPaddingRow(0, 318 if (use_close_button) {
495 kWaitingViewVerticalPadding - 319 layout->StartRow(0, 1);
496 ConstrainedWindowConstants::kCloseButtonPadding - 320 layout->AddView(CreateCloseButton(listener));
497 close_button->GetPreferredSize().height()); 321 }
498 layout->StartRow(0, CONTENT_ROW); 322
499 SpinnerProgressIndicator* throbber = new SpinnerProgressIndicator(); 323 layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
324 layout->StartRow(0, 0);
500 layout->AddView(throbber); 325 layout->AddView(throbber);
501 326 layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
502 // Message 327 layout->StartRow(0, 0);
503 const int kMessageBuiltinTopPadding = 5;
504 layout->AddPaddingRow(0,
505 ConstrainedWindowConstants::kRowPadding -
506 kMessageBuiltinTopPadding);
507 layout->StartRow(0, CONTENT_ROW);
508 views::Label* label = CreateLabel();
509 label->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
510 label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
511 layout->AddView(label); 328 layout->AddView(label);
512 329 layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
513 // Start the throbber.
514 throbber->SetIndeterminate(true);
515 } 330 }
516 331
517 WaitingView::~WaitingView() { 332 // SuggestedExtensionsLayout ---------------------------------------------------
333
334 // TODO(groby): Extremely fragile code, relies on order and number of fields.
335 // Would probably be better off as GridLayout or similar. Also see review
336 // comments on http://codereview.chromium.org/10909183
337
338 // A LayoutManager used by a row of the IntentsView. It is similar
339 // to a BoxLayout, but it right aligns the rightmost view (which is the install
340 // button). It also uses the maximum height of all views in the row as a
341 // preferred height so it doesn't change when the install button is hidden.
342 class SuggestedExtensionsLayout : public views::LayoutManager {
343 public:
344 SuggestedExtensionsLayout();
345 virtual ~SuggestedExtensionsLayout();
346
347 // Implementation of views::LayoutManager.
348 virtual void Layout(views::View* host) OVERRIDE;
349 virtual gfx::Size GetPreferredSize(views::View* host) OVERRIDE;
350
351 private:
352 DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsLayout);
353 };
354
355 SuggestedExtensionsLayout::SuggestedExtensionsLayout() {
518 } 356 }
519 357
358 SuggestedExtensionsLayout::~SuggestedExtensionsLayout() {
359 }
360
361 void SuggestedExtensionsLayout::Layout(views::View* host) {
362 gfx::Rect child_area(host->GetLocalBounds());
363 child_area.Inset(host->GetInsets());
364 int x = child_area.x();
365 int y = child_area.y();
366
367 for (int i = 0; i < host->child_count(); ++i) {
368 views::View* child = host->child_at(i);
369 if (!child->visible())
370 continue;
371 gfx::Size size(child->GetPreferredSize());
372 gfx::Rect child_bounds(x, y, size.width(), child_area.height());
373 if (i == host->child_count() - 1) {
374 // Last child (the install button) should be right aligned.
375 child_bounds.set_x(std::max(child_area.width() - size.width(), x));
376 } else if (i == 1) {
377 // Label is considered fixed width, to align ratings widget.
378 DCHECK_LE(size.width(), WebIntentPicker::kTitleLinkMaxWidth);
379 x += WebIntentPicker::kTitleLinkMaxWidth +
380 views::kRelatedControlHorizontalSpacing;
381 } else {
382 x += size.width() + views::kRelatedControlHorizontalSpacing;
383 }
384 // Clamp child view bounds to |child_area|.
385 child->SetBoundsRect(child_bounds.Intersect(child_area));
386 }
387 }
388
389 gfx::Size SuggestedExtensionsLayout::GetPreferredSize(views::View* host) {
390 int width = 0;
391 int height = 0;
392 for (int i = 0; i < host->child_count(); ++i) {
393 views::View* child = host->child_at(i);
394 gfx::Size size(child->GetPreferredSize());
395 // The preferred height includes visible and invisible children. This
396 // prevents jank when a child is hidden.
397 height = std::max(height, size.height());
398 if (!child->visible())
399 continue;
400 if (i != 0)
401 width += views::kRelatedControlHorizontalSpacing;
402 }
403 gfx::Insets insets(host->GetInsets());
404 return gfx::Size(width + insets.width(), height + insets.height());
405 }
520 406
521 // IntentRowView -------------------------------------------------- 407 // IntentRowView --------------------------------------------------
522 408
523 // A view for each row in the IntentsView. It displays information 409 // A view for each row in the IntentsView. It displays information
524 // for both installed and suggested intent handlers. 410 // for both installed and suggested intent handlers.
525 class IntentRowView : public views::View, 411 class IntentRowView : public views::View,
526 public views::ButtonListener, 412 public views::ButtonListener,
527 public views::LinkListener { 413 public views::LinkListener {
528 public: 414 public:
529 enum ActionType { 415 enum ActionType {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 WebIntentPicker::kTitleLinkMaxWidth, 538 WebIntentPicker::kTitleLinkMaxWidth,
653 ui::ELIDE_AT_END); 539 ui::ELIDE_AT_END);
654 540
655 const gfx::ImageSkia* icon = NULL; 541 const gfx::ImageSkia* icon = NULL;
656 StarsView* stars = NULL; 542 StarsView* stars = NULL;
657 views::Label* label = NULL; 543 views::Label* label = NULL;
658 IntentRowView* view; 544 IntentRowView* view;
659 if (service != NULL) { 545 if (service != NULL) {
660 view = new IntentRowView(ACTION_INVOKE, tag); 546 view = new IntentRowView(ACTION_INVOKE, tag);
661 icon = service->favicon.ToImageSkia(); 547 icon = service->favicon.ToImageSkia();
662 label = CreateLabel(); 548 label = new views::Label(elided_title);
663 label->SetText(elided_title);
664 } else { 549 } else {
665 view = new IntentRowView(ACTION_INSTALL, tag); 550 view = new IntentRowView(ACTION_INSTALL, tag);
666 view->extension_id_ = extension->id; 551 view->extension_id_ = extension->id;
667 icon = extension->icon.ToImageSkia(); 552 icon = extension->icon.ToImageSkia();
668 views::Link* link = CreateLink(); 553 views::Link* link = new views::Link(elided_title);
669 link->SetText(elided_title);
670 link->set_listener(view); 554 link->set_listener(view);
671 label = link; 555 label = link;
672 stars = new StarsView(extension->average_rating); 556 stars = new StarsView(extension->average_rating);
673 } 557 }
674 558
675 view->delegate_ = delegate; 559 view->delegate_ = delegate;
676 560
677 views::GridLayout* grid_layout = new views::GridLayout(view); 561 view->SetLayoutManager(new SuggestedExtensionsLayout);
678 view->SetLayoutManager(grid_layout);
679
680 views::ColumnSet* columns = grid_layout->AddColumnSet(0);
681 columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
682 GridLayout::USE_PREF, 0, 0); // Icon.
683 columns->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
684 columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
685 GridLayout::FIXED, WebIntentPicker::kTitleLinkMaxWidth, 0);
686 const int kStarRatingHorizontalSpacing = 20;
687 columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
688 if (stars != NULL) {
689 columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
690 GridLayout::USE_PREF, 0, 0); // Star rating.
691 columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
692 }
693 columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
694 GridLayout::FIXED, preferred_width, 0); // Button.
695
696 grid_layout->StartRow(0, 0);
697 562
698 view->icon_ = new views::ImageView(); 563 view->icon_ = new views::ImageView();
564
699 view->icon_->SetImage(icon); 565 view->icon_->SetImage(icon);
700 grid_layout->AddView(view->icon_); 566 view->AddChildView(view->icon_);
701 567
702 view->title_link_ = label; 568 view->title_link_ = label;
703 grid_layout->AddView(view->title_link_); 569 view->AddChildView(view->title_link_);
704 570
705 if (stars != NULL) { 571 if (stars != NULL) {
706 view->stars_ = stars; 572 view->stars_ = stars;
707 grid_layout->AddView(view->stars_); 573 view->AddChildView(view->stars_);
708 } 574 }
709 575
710 view->install_button_ = new ThrobberNativeTextButton( 576 view->install_button_ = new ThrobberNativeTextButton(
711 view, view->GetActionButtonMessage()); 577 view, view->GetActionButtonMessage());
712 view->install_button_->set_preferred_width(preferred_width); 578 view->install_button_->set_preferred_width(preferred_width);
713 grid_layout->AddView(view->install_button_); 579 view->AddChildView(view->install_button_);
714 580
715 return view; 581 return view;
716 } 582 }
717 583
718 IntentRowView::~IntentRowView() {} 584 IntentRowView::~IntentRowView() {}
719 585
720 void IntentRowView::ButtonPressed(views::Button* sender, 586 void IntentRowView::ButtonPressed(views::Button* sender,
721 const ui::Event& event) { 587 const ui::Event& event) {
722 if (type_ == ACTION_INSTALL) 588 if (type_ == ACTION_INSTALL)
723 delegate_->OnExtensionInstallClicked(extension_id_); 589 delegate_->OnExtensionInstallClicked(extension_id_);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 if (type_ == ACTION_INVOKE) 634 if (type_ == ACTION_INVOKE)
769 message_id = IDS_INTENT_PICKER_SELECT_INTENT; 635 message_id = IDS_INTENT_PICKER_SELECT_INTENT;
770 else if (type_ == ACTION_INSTALL) 636 else if (type_ == ACTION_INSTALL)
771 message_id = IDS_INTENT_PICKER_INSTALL_EXTENSION; 637 message_id = IDS_INTENT_PICKER_INSTALL_EXTENSION;
772 else 638 else
773 NOTREACHED(); 639 NOTREACHED();
774 640
775 return l10n_util::GetStringUTF16(message_id); 641 return l10n_util::GetStringUTF16(message_id);
776 } 642 }
777 643
778
779 // IntentsView ----------------------------------------------------- 644 // IntentsView -----------------------------------------------------
780 645
781 // A view that contains both installed services and suggested extensions 646 // A view that contains both installed services and suggested extensions
782 // from the Chrome Web Store that provide an intent service matching the 647 // from the Chrome Web Store that provide an intent service matching the
783 // action/type pair. 648 // action/type pair.
784 class IntentsView : public views::View { 649 class IntentsView : public views::View {
785 public: 650 public:
786 IntentsView(const WebIntentPickerModel* model, 651 IntentsView(const WebIntentPickerModel* model,
787 IntentRowView::Delegate* delegate); 652 IntentRowView::Delegate* delegate);
788 653
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 void IntentsView::Update() { 695 void IntentsView::Update() {
831 RemoveAllChildViews(true); 696 RemoveAllChildViews(true);
832 697
833 ThrobberNativeTextButton size_helper( 698 ThrobberNativeTextButton size_helper(
834 NULL, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION)); 699 NULL, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION));
835 size_helper.SetText( 700 size_helper.SetText(
836 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_SELECT_INTENT)); 701 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_SELECT_INTENT));
837 button_width_ = std::max( 702 button_width_ = std::max(
838 kButtonWidth, size_helper.GetPreferredSize().width()); 703 kButtonWidth, size_helper.GetPreferredSize().width());
839 704
840 const int kAppRowVerticalSpacing = 10; 705 views::BoxLayout* layout = new views::BoxLayout(
841 views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical, 706 views::BoxLayout::kVertical, 0, 0, views::kRelatedControlVerticalSpacing);
842 0, 0, kAppRowVerticalSpacing);
843 SetLayoutManager(layout); 707 SetLayoutManager(layout);
844 708
845 int available_rows = kMaxRowCount; 709 int available_rows = kMaxRowCount;
846 710
847 for (size_t i = 0; 711 for (size_t i = 0;
848 available_rows > 0 && i < model_->GetInstalledServiceCount(); 712 available_rows > 0 && i < model_->GetInstalledServiceCount();
849 ++i, --available_rows) { 713 ++i, --available_rows) {
850 const WebIntentPickerModel::InstalledService& service = 714 const WebIntentPickerModel::InstalledService& service =
851 model_->GetInstalledServiceAt(i); 715 model_->GetInstalledServiceAt(i);
852 AddChildView(IntentRowView::CreateHandlerRow(&service, NULL, i, 716 AddChildView(IntentRowView::CreateHandlerRow(&service, NULL, i,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
884 return old_width - kButtonWidth + button_width_; 748 return old_width - kButtonWidth + button_width_;
885 } 749 }
886 750
887 void IntentsView::OnEnabledChanged() { 751 void IntentsView::OnEnabledChanged() {
888 EnableChildViews(this, enabled()); 752 EnableChildViews(this, enabled());
889 View::OnEnabledChanged(); 753 View::OnEnabledChanged();
890 } 754 }
891 755
892 } // namespace 756 } // namespace
893 757
894
895 // WebIntentPickerViews -------------------------------------------------------- 758 // WebIntentPickerViews --------------------------------------------------------
896 759
897 // Views implementation of WebIntentPicker. 760 // Views implementation of WebIntentPicker.
898 class WebIntentPickerViews : public views::ButtonListener, 761 class WebIntentPickerViews : public views::ButtonListener,
899 public views::WidgetDelegate, 762 public views::DialogDelegate,
900 public views::LinkListener, 763 public views::LinkListener,
901 public WebIntentPicker, 764 public WebIntentPicker,
902 public WebIntentPickerModelObserver, 765 public WebIntentPickerModelObserver,
903 public IntentRowView::Delegate { 766 public IntentRowView::Delegate {
904 public: 767 public:
905 WebIntentPickerViews(TabContents* tab_contents, 768 WebIntentPickerViews(TabContents* tab_contents,
906 WebIntentPickerDelegate* delegate, 769 WebIntentPickerDelegate* delegate,
907 WebIntentPickerModel* model); 770 WebIntentPickerModel* model);
908 virtual ~WebIntentPickerViews(); 771 virtual ~WebIntentPickerViews();
909 772
910 // views::ButtonListener implementation. 773 // views::ButtonListener implementation.
911 // This method is called when the user cancels the picker dialog. 774 // This method is called when the user cancels the picker dialog.
912 virtual void ButtonPressed(views::Button* sender, 775 virtual void ButtonPressed(views::Button* sender,
913 const ui::Event& event) OVERRIDE; 776 const ui::Event& event) OVERRIDE;
914 777
915 // views::WidgetDelegate implementation. 778 // views::DialogDelegate implementation.
916 virtual void WindowClosing() OVERRIDE; 779 virtual void WindowClosing() OVERRIDE;
917 virtual void DeleteDelegate() OVERRIDE; 780 virtual void DeleteDelegate() OVERRIDE;
918 virtual views::Widget* GetWidget() OVERRIDE; 781 virtual views::Widget* GetWidget() OVERRIDE;
919 virtual const views::Widget* GetWidget() const OVERRIDE; 782 virtual const views::Widget* GetWidget() const OVERRIDE;
920 virtual views::View* GetContentsView() OVERRIDE; 783 virtual views::View* GetContentsView() OVERRIDE;
784 virtual int GetDialogButtons() const OVERRIDE;
785 virtual bool Cancel() OVERRIDE;
921 786
922 // LinkListener implementation. 787 // LinkListener implementation.
923 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 788 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
924 789
925 // WebIntentPicker implementation. 790 // WebIntentPicker implementation.
926 virtual void Close() OVERRIDE; 791 virtual void Close() OVERRIDE;
927 virtual void SetActionString(const string16& action) OVERRIDE; 792 virtual void SetActionString(const string16& action) OVERRIDE;
928 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; 793 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
929 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE; 794 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE;
930 virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE; 795 virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE;
(...skipping 14 matching lines...) Expand all
945 virtual void OnExtensionInstallClicked( 810 virtual void OnExtensionInstallClicked(
946 const std::string& extension_id) OVERRIDE; 811 const std::string& extension_id) OVERRIDE;
947 virtual void OnExtensionLinkClicked( 812 virtual void OnExtensionLinkClicked(
948 const std::string& extension_id, 813 const std::string& extension_id,
949 WindowOpenDisposition disposition) OVERRIDE; 814 WindowOpenDisposition disposition) OVERRIDE;
950 virtual void OnActionButtonClicked( 815 virtual void OnActionButtonClicked(
951 IntentRowView::ActionType type, 816 IntentRowView::ActionType type,
952 size_t tag) OVERRIDE; 817 size_t tag) OVERRIDE;
953 818
954 private: 819 private:
955 enum WebIntentPickerViewsState {
956 INITIAL,
957 WAITING,
958 NO_SERVICES,
959 LIST_SERVICES,
960 INLINE_SERVICE,
961 } state_;
962
963 // Update picker contents to reflect the current state of the model. 820 // Update picker contents to reflect the current state of the model.
964 void UpdateContents(); 821 void UpdateContents();
965 822
966 // Shows a spinner and notifies the user that we are waiting for information
967 // from the Chrome Web Store.
968 void ShowWaitingForSuggestions();
969
970 // Updates the dialog with the list of available services, suggestions, 823 // Updates the dialog with the list of available services, suggestions,
971 // and a nice link to CWS to find more suggestions. This is the "Main" 824 // and a nice link to CWS to find more suggestions. This is the "Main"
972 // view of the picker. 825 // view of the picker.
973 void ShowAvailableServices(); 826 void ShowAvailableServices();
974 827
975 // Informs the user that there are no services available to handle 828 // Informs the user that there are no services available to handle
976 // the intent, and that there are no suggestions from the Chrome Web Store. 829 // the intent, and that there are no suggestions from the Chrome Web Store.
977 void ShowNoServicesMessage(); 830 void ShowNoServicesMessage();
978 831
979 // Restore the contents of the picker to the initial contents. 832 // Restore the contents of the picker to the initial contents.
980 void ResetContents(); 833 void ResetContents();
981 834
982 // Resize the constrained window to the size of its contents. 835 // Resize the constrained window to the size of its contents.
983 void SizeToContents(); 836 void SizeToContents();
984 837
985 // Clear the contents of the picker. 838 // Clear the contents of the picker.
986 void ClearContents(); 839 void ClearContents();
987 840
988 // Returns the service selection question text used in the title 841 // Returns the service selection question text used in the title
989 // of the picker. 842 // of the picker.
990 const string16 GetActionTitle(); 843 const string16 GetActionTitle();
991 844
992 // Refresh the icon for the inline disposition service that is being
993 // displayed.
994 void RefreshInlineServiceIcon();
995
996 // Refresh the extensions control in the picker.
997 void RefreshExtensions();
998
999 // A weak pointer to the WebIntentPickerDelegate to notify when the user 845 // A weak pointer to the WebIntentPickerDelegate to notify when the user
1000 // chooses a service or cancels. 846 // chooses a service or cancels.
1001 WebIntentPickerDelegate* delegate_; 847 WebIntentPickerDelegate* delegate_;
1002 848
1003 // A weak pointer to the picker model. 849 // A weak pointer to the picker model.
1004 WebIntentPickerModel* model_; 850 WebIntentPickerModel* model_;
1005 851
1006 // A weak pointer to the action string label. 852 // A weak pointer to the action string label.
1007 // Created locally, owned by Views. 853 // Created locally, owned by Views.
1008 views::Label* action_label_; 854 views::Label* action_label_;
1009 855
856 // A weak pointer to the header label for the extension suggestions.
857 // Created locally, owned by Views.
858 views::Label* suggestions_label_;
859
1010 // A weak pointer to the intents view. 860 // A weak pointer to the intents view.
1011 // Created locally, owned by Views view hierarchy. 861 // Created locally, owned by Views view hierarchy.
1012 IntentsView* extensions_; 862 IntentsView* extensions_;
1013 863
1014 // Delegate for inline disposition tab contents. 864 // Delegate for inline disposition tab contents.
1015 scoped_ptr<WebIntentInlineDispositionDelegate> inline_disposition_delegate_; 865 scoped_ptr<WebIntentInlineDispositionDelegate> inline_disposition_delegate_;
1016 866
1017 // A weak pointer to the TabContents this picker is in. 867 // A weak pointer to the TabContents this picker is in.
1018 TabContents* tab_contents_; 868 TabContents* tab_contents_;
1019 869
1020 // A weak pointer to the WebView that hosts the WebContents being displayed. 870 // A weak pointer to the WebView that hosts the WebContents being displayed.
1021 // Created locally, owned by Views. 871 // Created locally, owned by Views.
1022 views::WebView* webview_; 872 views::WebView* webview_;
1023 873
1024 // A weak pointer to the view that contains all other views in the picker. 874 // A weak pointer to the view that contains all other views in the picker.
1025 // Created locally, owned by Views. 875 // Created locally, owned by Views.
1026 views::View* contents_; 876 views::View* contents_;
1027 877
1028 // A weak pointer to the constrained window. 878 // A weak pointer to the constrained window.
1029 // Created locally, owned by Views. 879 // Created locally, owned by Views.
1030 ConstrainedWindowViews* window_; 880 ConstrainedWindowViews* window_;
1031 881
1032 // A weak pointer to the more suggestions link. 882 // A weak pointer to the more suggestions link.
1033 // Created locally, owned by Views. 883 // Created locally, owned by Views.
1034 views::Link* more_suggestions_link_; 884 views::Link* more_suggestions_link_;
1035 885
1036 // The icon for the inline disposition service.
1037 views::ImageView* inline_service_icon_;
1038
1039 // A weak pointer to the choose another service link. 886 // A weak pointer to the choose another service link.
1040 // Created locally, owned by Views. 887 // Created locally, owned by Views.
1041 views::Link* choose_another_service_link_; 888 views::Link* choose_another_service_link_;
1042 889
1043 // Weak pointer to "Waiting for CWS" display. Owned by parent view. 890 // Weak pointer to "Waiting for CWS" display. Owned by parent view.
1044 WaitingView* waiting_view_; 891 WaitingView* waiting_view_;
1045 892
893 // Set to true when displaying the inline disposition web contents. Used to
894 // prevent laying out the inline disposition widgets twice.
895 bool displaying_web_contents_;
896
1046 // The text for the current action. 897 // The text for the current action.
1047 string16 action_text_; 898 string16 action_text_;
1048 899
1049 // Ownership of the WebContents we are displaying in the inline disposition. 900 // Ownership of the WebContents we are displaying in the inline disposition.
1050 scoped_ptr<WebContents> inline_web_contents_; 901 scoped_ptr<WebContents> inline_web_contents_;
1051 902
1052 // Indicate if dialog should display its own close button. 903 // Indicate if dialog should display its own close button.
1053 // TODO(groby): Only relevant until new ConstrainedWindow is implemented, 904 // TODO(groby): Only relevant until new ConstrainedWindow is implemented,
1054 // from then on always true. 905 // from then on always true.
1055 bool use_close_button_; 906 bool use_close_button_;
1056 907
1057 // Signals if the picker can be closed. False during extension install. 908 // Signals if the picker can be closed. False during extension install.
1058 bool can_close_; 909 bool can_close_;
1059 910
1060 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews); 911 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews);
1061 }; 912 };
1062 913
1063 // static 914 // static
1064 WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents, 915 WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents,
1065 WebIntentPickerDelegate* delegate, 916 WebIntentPickerDelegate* delegate,
1066 WebIntentPickerModel* model) { 917 WebIntentPickerModel* model) {
1067 TabContents* tab_contents = TabContents::FromWebContents(web_contents); 918 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
1068 return new WebIntentPickerViews(tab_contents, delegate, model); 919 return new WebIntentPickerViews(tab_contents, delegate, model);
1069 } 920 }
1070 921
1071 WebIntentPickerViews::WebIntentPickerViews(TabContents* tab_contents, 922 WebIntentPickerViews::WebIntentPickerViews(TabContents* tab_contents,
1072 WebIntentPickerDelegate* delegate, 923 WebIntentPickerDelegate* delegate,
1073 WebIntentPickerModel* model) 924 WebIntentPickerModel* model)
1074 : state_(INITIAL), 925 : delegate_(delegate),
1075 delegate_(delegate),
1076 model_(model), 926 model_(model),
1077 action_label_(NULL), 927 action_label_(NULL),
928 suggestions_label_(NULL),
1078 extensions_(NULL), 929 extensions_(NULL),
1079 tab_contents_(tab_contents), 930 tab_contents_(tab_contents),
1080 webview_(new views::WebView(tab_contents->profile())), 931 webview_(new views::WebView(tab_contents->profile())),
1081 window_(NULL), 932 window_(NULL),
1082 more_suggestions_link_(NULL), 933 more_suggestions_link_(NULL),
1083 inline_service_icon_(NULL),
1084 choose_another_service_link_(NULL), 934 choose_another_service_link_(NULL),
1085 waiting_view_(NULL), 935 waiting_view_(NULL),
936 displaying_web_contents_(false),
1086 can_close_(true) { 937 can_close_(true) {
1087 bool enable_chrome_style = chrome::IsFramelessConstrainedDialogEnabled(); 938 bool enable_chrome_style = chrome::IsFramelessConstrainedDialogEnabled();
1088 use_close_button_ = enable_chrome_style; 939 use_close_button_ = enable_chrome_style;
1089 940
1090 model_->set_observer(this); 941 model_->set_observer(this);
1091 contents_ = new views::View(); 942 contents_ = new views::View();
1092 contents_->set_background(views::Background::CreateSolidBackground( 943 // Show the dialog.
1093 ConstrainedWindow::GetBackgroundColor())); 944 window_ = new ConstrainedWindowViews(tab_contents->web_contents(),
945 this,
946 enable_chrome_style);
1094 947
1095 // Show the dialog.
1096 window_ = new ConstrainedWindowViews(tab_contents->web_contents(), this,
1097 enable_chrome_style,
1098 ConstrainedWindowViews::NO_INSETS);
1099 if (model_->IsInlineDisposition()) 948 if (model_->IsInlineDisposition())
1100 OnInlineDisposition(string16(), model_->inline_disposition_url()); 949 OnInlineDisposition(string16(), model_->inline_disposition_url());
1101 else 950 else
1102 UpdateContents(); 951 UpdateContents();
1103 } 952 }
1104 953
1105 WebIntentPickerViews::~WebIntentPickerViews() { 954 WebIntentPickerViews::~WebIntentPickerViews() {
1106 model_->set_observer(NULL); 955 model_->set_observer(NULL);
1107 } 956 }
1108 957
(...skipping 15 matching lines...) Expand all
1124 } 973 }
1125 974
1126 const views::Widget* WebIntentPickerViews::GetWidget() const { 975 const views::Widget* WebIntentPickerViews::GetWidget() const {
1127 return contents_->GetWidget(); 976 return contents_->GetWidget();
1128 } 977 }
1129 978
1130 views::View* WebIntentPickerViews::GetContentsView() { 979 views::View* WebIntentPickerViews::GetContentsView() {
1131 return contents_; 980 return contents_;
1132 } 981 }
1133 982
983 int WebIntentPickerViews::GetDialogButtons() const {
984 return ui::DIALOG_BUTTON_NONE;
985 }
986
987 bool WebIntentPickerViews::Cancel() {
988 return can_close_;
989 }
990
1134 void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) { 991 void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) {
1135 if (source == more_suggestions_link_) { 992 if (source == more_suggestions_link_) {
1136 delegate_->OnSuggestionsLinkClicked( 993 delegate_->OnSuggestionsLinkClicked(
1137 chrome::DispositionFromEventFlags(event_flags)); 994 chrome::DispositionFromEventFlags(event_flags));
1138 } else if (source == choose_another_service_link_) { 995 } else if (source == choose_another_service_link_) {
1139 // Signal cancellation of inline disposition. 996 // Signal cancellation of inline disposition.
1140 delegate_->OnChooseAnotherService(); 997 delegate_->OnChooseAnotherService();
1141 ResetContents(); 998 ResetContents();
1142 } else { 999 } else {
1143 NOTREACHED(); 1000 NOTREACHED();
1144 } 1001 }
1145 } 1002 }
1146 1003
1147 void WebIntentPickerViews::Close() { 1004 void WebIntentPickerViews::Close() {
1148 window_->CloseConstrainedWindow(); 1005 window_->CloseConstrainedWindow();
1149 } 1006 }
1150 1007
1151 void WebIntentPickerViews::SetActionString(const string16& action) { 1008 void WebIntentPickerViews::SetActionString(const string16& action) {
1152 action_text_ = action; 1009 action_text_ = action;
1153 if (action_label_) { 1010
1011 if (action_label_)
1154 action_label_->SetText(GetActionTitle()); 1012 action_label_->SetText(GetActionTitle());
1155 contents_->Layout(); 1013 contents_->Layout();
1156 SizeToContents(); 1014 SizeToContents();
1157 }
1158 } 1015 }
1159 1016
1160 void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) { 1017 void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) {
1161 can_close_ = true; 1018 can_close_ = true;
1162 } 1019 }
1163 1020
1164 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) { 1021 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) {
1165 extensions_->StopThrobber(); 1022 extensions_->StopThrobber();
1166 extensions_->SetEnabled(true);
1167 more_suggestions_link_->SetEnabled(true); 1023 more_suggestions_link_->SetEnabled(true);
1168 can_close_ = true; 1024 can_close_ = true;
1169 contents_->Layout(); 1025 contents_->Layout();
1170 SizeToContents(); 1026 SizeToContents();
1171 1027
1172 // TODO(binji): What to display to user on failure? 1028 // TODO(binji): What to display to user on failure?
1173 } 1029 }
1174 1030
1175 void WebIntentPickerViews::OnInlineDispositionAutoResize( 1031 void WebIntentPickerViews::OnInlineDispositionAutoResize(
1176 const gfx::Size& size) { 1032 const gfx::Size& size) {
1177 webview_->SetPreferredSize(size); 1033 webview_->SetPreferredSize(size);
1178 contents_->Layout(); 1034 contents_->Layout();
1179 SizeToContents(); 1035 SizeToContents();
1180 } 1036 }
1181 1037
1182 void WebIntentPickerViews::OnPendingAsyncCompleted() { 1038 void WebIntentPickerViews::OnPendingAsyncCompleted() {
1183 UpdateContents(); 1039 UpdateContents();
1184 } 1040 }
1185 1041
1186 void WebIntentPickerViews::ShowNoServicesMessage() { 1042 void WebIntentPickerViews::ShowNoServicesMessage() {
1187 if (state_ == NO_SERVICES) 1043 ClearContents();
1188 return;
1189 state_ = NO_SERVICES;
1190 1044
1191 ClearContents(); 1045 views::GridLayout* grid_layout = new views::GridLayout(contents_);
1192 views::GridLayout* layout = new views::GridLayout(contents_); 1046 contents_->SetLayoutManager(grid_layout);
1193 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
1194 const int kContentBuiltinBottomPadding = 3;
1195 layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding,
1196 0,
1197 ConstrainedWindowConstants::kClientBottomPadding -
1198 kContentBuiltinBottomPadding,
1199 0);
1200 contents_->SetLayoutManager(layout);
1201 1047
1202 enum GridLayoutColumnSets { 1048 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
1203 HEADER_ROW, 1049 kContentAreaBorder, kContentAreaBorder);
1204 CONTENT_ROW, 1050 views::ColumnSet* main_cs = grid_layout->AddColumnSet(0);
1205 }; 1051 main_cs->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
1206 views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW); 1052 GridLayout::USE_PREF, 0, 0);
1207 header_cs->AddPaddingColumn(
1208 0, ConstrainedWindowConstants::kHorizontalPadding);
1209 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
1210 GridLayout::USE_PREF, 0, 0); // Title
1211 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
1212 GridLayout::USE_PREF, 0, 0); // Close button
1213 header_cs->AddPaddingColumn(
1214 0, ConstrainedWindowConstants::kCloseButtonPadding);
1215 1053
1216 views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW); 1054 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1217 content_cs->AddPaddingColumn(
1218 0, ConstrainedWindowConstants::kHorizontalPadding);
1219 content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1220 GridLayout::USE_PREF, 0, 0); // Body
1221 content_cs->AddPaddingColumn(
1222 0, ConstrainedWindowConstants::kHorizontalPadding);
1223 1055
1224 // Header 1056 grid_layout->StartRow(0, 0);
1225 layout->StartRow(0, HEADER_ROW); 1057 views::Label* header = new views::Label();
1226 views::Label* title = CreateTitleLabel(); 1058 header->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1227 title->SetText(l10n_util::GetStringUTF16( 1059 header->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
1060 header->SetText(l10n_util::GetStringUTF16(
1228 IDS_INTENT_PICKER_NO_SERVICES_TITLE)); 1061 IDS_INTENT_PICKER_NO_SERVICES_TITLE));
1229 layout->AddView(title); 1062 grid_layout->AddView(header);
1230 1063
1231 views::ImageButton* close_button = CreateCloseButton(this); 1064 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1232 layout->AddView(close_button);
1233 close_button->SetVisible(use_close_button_);
1234 1065
1235 // Content 1066 grid_layout->StartRow(0, 0);
1236 const int kHeaderBuiltinBottomPadding = 4; 1067 views::Label* body = new views::Label();
1237 const int kContentBuiltinTopPadding = 5;
1238 layout->AddPaddingRow(0,
1239 ConstrainedWindowConstants::kRowPadding -
1240 kHeaderBuiltinBottomPadding -
1241 kContentBuiltinTopPadding);
1242 layout->StartRow(0, CONTENT_ROW);
1243 views::Label* body = CreateLabel();
1244 body->SetMultiLine(true); 1068 body->SetMultiLine(true);
1069 body->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1245 body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES)); 1070 body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES));
1246 layout->AddView(body); 1071 grid_layout->AddView(body);
1247 1072
1248 int height = contents_->GetHeightForWidth(WebIntentPicker::kWindowMinWidth); 1073 int height = contents_->GetHeightForWidth(kWindowMinWidth);
1249 contents_->SetSize(gfx::Size(WebIntentPicker::kWindowMinWidth, height)); 1074 contents_->SetSize(gfx::Size(kWindowMinWidth, height));
1250 contents_->Layout();
1251 } 1075 }
1252 1076
1253 void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded( 1077 void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded(
1254 content::WebContents* web_contents) { 1078 content::WebContents* web_contents) {
1255 if (state_ == INLINE_SERVICE) 1079 if (displaying_web_contents_)
1256 return; 1080 return;
1257 state_ = INLINE_SERVICE;
1258 1081
1259 // Replace the picker with the inline disposition. 1082 // Replace the picker with the inline disposition.
1260 ClearContents(); 1083 ClearContents();
1084
1261 views::GridLayout* grid_layout = new views::GridLayout(contents_); 1085 views::GridLayout* grid_layout = new views::GridLayout(contents_);
1262 grid_layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
1263 grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
1264 ConstrainedWindowConstants::kClientBottomPadding, 0);
1265 contents_->SetLayoutManager(grid_layout); 1086 contents_->SetLayoutManager(grid_layout);
1266 1087
1267 enum GridLayoutColumnSets { 1088 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
1268 HEADER_ROW, 1089 kContentAreaBorder, kContentAreaBorder);
1269 SEPARATOR_ROW, 1090 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
1270 WEB_CONTENTS_ROW, 1091 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
1271 }; 1092 GridLayout::USE_PREF, 0, 0); // Icon.
1272 views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW); 1093 header_cs->AddPaddingColumn(0, 4);
1273 header_cs->AddPaddingColumn( 1094 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
1274 0, ConstrainedWindowConstants::kHorizontalPadding); 1095 GridLayout::USE_PREF, 0, 0); // Title.
1275 header_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, 1096 header_cs->AddPaddingColumn(0, 4);
1276 GridLayout::USE_PREF, 0, 0); // Icon, title, link. 1097 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
1277 header_cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 1098 GridLayout::USE_PREF, 0, 0); // Link.
1278 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0, 1099 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
1279 GridLayout::USE_PREF, 0, 0); // Close button. 1100 if (use_close_button_) {
1280 header_cs->AddPaddingColumn( 1101 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
1281 0, ConstrainedWindowConstants::kCloseButtonPadding); 1102 GridLayout::USE_PREF, 0, 0); // Close Button.
1103 }
1282 1104
1283 views::ColumnSet* sep_cs = grid_layout->AddColumnSet(SEPARATOR_ROW); 1105 views::ColumnSet* full_cs = grid_layout->AddColumnSet(1);
1284 sep_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, 1106 full_cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
1285 GridLayout::USE_PREF, 0, 0); // Separator. 1107 GridLayout::USE_PREF, 0, 0);
1286
1287 views::ColumnSet* contents_cs = grid_layout->AddColumnSet(WEB_CONTENTS_ROW);
1288 contents_cs->AddPaddingColumn(0, 1);
1289 contents_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
1290 GridLayout::USE_PREF, 0, 0); // Web contents.
1291 contents_cs->AddPaddingColumn(0, 1);
1292
1293 // Header.
1294 grid_layout->StartRow(0, HEADER_ROW);
1295 1108
1296 const WebIntentPickerModel::InstalledService* service = 1109 const WebIntentPickerModel::InstalledService* service =
1297 model_->GetInstalledServiceWithURL(model_->inline_disposition_url()); 1110 model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
1298 1111
1299 if (!inline_service_icon_) 1112 // Header row.
1300 inline_service_icon_ = new views::ImageView(); 1113 grid_layout->StartRow(0, 0);
1301 inline_service_icon_->SetImage(service->favicon.ToImageSkia()); 1114 views::ImageView* icon = new views::ImageView();
1115 icon->SetImage(service->favicon.ToImageSkia());
1116 grid_layout->AddView(icon);
1302 1117
1303 views::Label* title = CreateLabel(); 1118 string16 elided_title = ui::ElideText(
1304 title->SetText(ui::ElideText( 1119 service->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END);
1305 service->title, title->font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END)); 1120 views::Label* title = new views::Label(elided_title);
1121 grid_layout->AddView(title);
1122 // Add link for "choose another service" if other suggestions are available
1123 // or if more than one (the current) service is installed.
1124 if (model_->show_use_another_service() &&
1125 (model_->GetInstalledServiceCount() > 1 ||
1126 model_->GetSuggestedExtensionCount())) {
1127 choose_another_service_link_ = new views::Link(
1128 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
1129 grid_layout->AddView(choose_another_service_link_);
1130 choose_another_service_link_->set_listener(this);
1131 }
1306 1132
1307 if (!choose_another_service_link_) 1133 if (use_close_button_)
1308 choose_another_service_link_ = CreateLink(); 1134 grid_layout->AddView(CreateCloseButton(this));
1309 choose_another_service_link_->SetText(l10n_util::GetStringUTF16(
1310 IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
1311 choose_another_service_link_->set_listener(this);
1312 1135
1313 grid_layout->AddView(CreateInlineDispositionHeader( 1136 // Inline web contents row.
1314 inline_service_icon_, title, choose_another_service_link_)); 1137 grid_layout->StartRow(0, 1);
1315 choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model_)); 1138 grid_layout->AddView(webview_, 1, 1, GridLayout::CENTER,
1139 GridLayout::CENTER, 0, 0);
1140 contents_->Layout();
1141 SizeToContents();
1142 displaying_web_contents_ = true;
1143 }
1316 1144
1317 views::ImageButton* close_button = CreateCloseButton(this); 1145 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
1318 grid_layout->AddView(close_button); 1146 if (waiting_view_ && !model->IsWaitingForSuggestions())
1319 close_button->SetVisible(use_close_button_); 1147 UpdateContents();
1320 1148
1321 // Separator. 1149 if (suggestions_label_) {
1322 const int kHeaderBuiltinBottomPadding = 4; 1150 string16 label_text = model->GetSuggestionsLinkText();
1323 grid_layout->AddPaddingRow(0, 1151 suggestions_label_->SetText(label_text);
1324 ConstrainedWindowConstants::kRowPadding - 1152 suggestions_label_->SetVisible(!label_text.empty());
1325 kHeaderBuiltinBottomPadding); 1153 }
1326 grid_layout->StartRow(0, SEPARATOR_ROW);
1327 grid_layout->AddView(new views::Separator());
1328 1154
1329 // Inline web contents. 1155 if (extensions_)
1330 const int kSeparatorBottomPadding = 3; 1156 extensions_->Update();
1331 grid_layout->AddPaddingRow(0, kSeparatorBottomPadding); 1157 contents_->Layout();
1332 grid_layout->StartRow(0, WEB_CONTENTS_ROW); 1158 SizeToContents();
1333 grid_layout->AddView(webview_); 1159 }
1160
1161 void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model,
1162 size_t index) {
1163 // TODO(groby): Update favicons on extensions_;
1164 contents_->Layout();
1165 SizeToContents();
1166 }
1167
1168 void WebIntentPickerViews::OnExtensionIconChanged(
1169 WebIntentPickerModel* model,
1170 const std::string& extension_id) {
1171 if (extensions_)
1172 extensions_->Update();
1334 1173
1335 contents_->Layout(); 1174 contents_->Layout();
1336 SizeToContents(); 1175 SizeToContents();
1337 } 1176 }
1338 1177
1339 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
1340 if (state_ == WAITING && !model->IsWaitingForSuggestions())
1341 UpdateContents();
1342
1343 if (choose_another_service_link_) {
1344 choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model));
1345 contents_->Layout();
1346 SizeToContents();
1347 }
1348
1349 if (extensions_)
1350 RefreshExtensions();
1351 }
1352
1353 void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model,
1354 size_t index) {
1355 // TODO(groby): Update favicons on extensions_;
1356 if (inline_service_icon_)
1357 RefreshInlineServiceIcon();
1358 if (extensions_)
1359 RefreshExtensions();
1360 }
1361
1362 void WebIntentPickerViews::OnExtensionIconChanged(
1363 WebIntentPickerModel* model,
1364 const std::string& extension_id) {
1365 OnFaviconChanged(model, -1);
1366 }
1367
1368 void WebIntentPickerViews::OnInlineDisposition( 1178 void WebIntentPickerViews::OnInlineDisposition(
1369 const string16&, const GURL& url) { 1179 const string16&, const GURL& url) {
1370 if (!webview_) 1180 if (!webview_)
1371 webview_ = new views::WebView(tab_contents_->profile()); 1181 webview_ = new views::WebView(tab_contents_->profile());
1372 1182
1373 inline_web_contents_.reset(delegate_->CreateWebContentsForInlineDisposition( 1183 inline_web_contents_.reset(delegate_->CreateWebContentsForInlineDisposition(
1374 tab_contents_->profile(), url)); 1184 tab_contents_->profile(), url));
1375 // Does not take ownership, so we keep a scoped_ptr 1185 // Does not take ownership, so we keep a scoped_ptr
1376 // for the WebContents locally. 1186 // for the WebContents locally.
1377 webview_->SetWebContents(inline_web_contents_.get()); 1187 webview_->SetWebContents(inline_web_contents_.get());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 model_->GetInstalledServiceAt(tag); 1228 model_->GetInstalledServiceAt(tag);
1419 delegate_->OnServiceChosen(service.url, service.disposition, 1229 delegate_->OnServiceChosen(service.url, service.disposition,
1420 WebIntentPickerDelegate::kEnableDefaults); 1230 WebIntentPickerDelegate::kEnableDefaults);
1421 } 1231 }
1422 1232
1423 void WebIntentPickerViews::UpdateContents() { 1233 void WebIntentPickerViews::UpdateContents() {
1424 if (model_ && model_->IsInlineDisposition()) 1234 if (model_ && model_->IsInlineDisposition())
1425 return; 1235 return;
1426 1236
1427 if (model_ && model_->IsWaitingForSuggestions()) { 1237 if (model_ && model_->IsWaitingForSuggestions()) {
1428 ShowWaitingForSuggestions(); 1238 ClearContents();
1239 contents_->SetLayoutManager(new views::FillLayout());
1240 waiting_view_ = new WaitingView(this, use_close_button_);
1241 contents_->AddChildView(waiting_view_);
1242 int height = contents_->GetHeightForWidth(kWindowMinWidth);
1243 contents_->SetSize(gfx::Size(kWindowMinWidth, height));
1244 contents_->Layout();
1429 } else if (model_ && (model_->GetInstalledServiceCount() || 1245 } else if (model_ && (model_->GetInstalledServiceCount() ||
1430 model_->GetSuggestedExtensionCount())) { 1246 model_->GetSuggestedExtensionCount())) {
1431 ShowAvailableServices(); 1247 ShowAvailableServices();
1432 } else { 1248 } else {
1433 ShowNoServicesMessage(); 1249 ShowNoServicesMessage();
1434 } 1250 }
1435 SizeToContents(); 1251 SizeToContents();
1436 } 1252 }
1437 1253
1438 void WebIntentPickerViews::ShowWaitingForSuggestions() {
1439 if (state_ == WAITING)
1440 return;
1441 state_ = WAITING;
1442 ClearContents();
1443 contents_->SetLayoutManager(new views::FillLayout());
1444 waiting_view_ = new WaitingView(this, use_close_button_);
1445 contents_->AddChildView(waiting_view_);
1446 int height = contents_->GetHeightForWidth(kWindowMinWidth);
1447 contents_->SetSize(gfx::Size(kWindowMinWidth, height));
1448 contents_->Layout();
1449 }
1450
1451 const string16 WebIntentPickerViews::GetActionTitle() { 1254 const string16 WebIntentPickerViews::GetActionTitle() {
1452 return action_text_.empty() ? 1255 return (!action_text_.empty()) ?
1453 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE) : 1256 action_text_ :
1454 action_text_; 1257 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE);
1455 } 1258 }
1456 1259
1457 void WebIntentPickerViews::ShowAvailableServices() { 1260 void WebIntentPickerViews::ShowAvailableServices() {
1261 enum {
1262 kHeaderRowColumnSet, // Column set for header layout.
1263 kFullWidthColumnSet, // Column set with a single full-width column.
1264 kIndentedFullWidthColumnSet, // Single full-width column, indented.
1265 };
1266
1458 ClearContents(); 1267 ClearContents();
1459 state_ = LIST_SERVICES; 1268 displaying_web_contents_ = false;
1269
1460 extensions_ = new IntentsView(model_, this); 1270 extensions_ = new IntentsView(model_, this);
1461 gfx::Size min_size = gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0);
1462 1271
1463 views::GridLayout* grid_layout = new views::GridLayout(contents_); 1272 views::GridLayout* grid_layout = new views::GridLayout(contents_);
1464 grid_layout->set_minimum_size(min_size);
1465 const int kIconBuiltinBottomPadding = 4;
1466 grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding,
1467 0,
1468 ConstrainedWindowConstants::kClientBottomPadding -
1469 kIconBuiltinBottomPadding,
1470 0);
1471 contents_->SetLayoutManager(grid_layout); 1273 contents_->SetLayoutManager(grid_layout);
1472 1274
1473 enum GridLayoutColumnSets { 1275 grid_layout->set_minimum_size(
1474 HEADER_ROW, 1276 gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0));
1475 CONTENT_ROW, 1277 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
1476 }; 1278 kContentAreaBorder, kContentAreaBorder);
1477 views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW); 1279 views::ColumnSet* header_cs = grid_layout->AddColumnSet(kHeaderRowColumnSet);
1478 header_cs->AddPaddingColumn(
1479 0, ConstrainedWindowConstants::kHorizontalPadding);
1480 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1, 1280 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
1481 GridLayout::USE_PREF, 0, 0); // Action title 1281 GridLayout::USE_PREF, 0, 0); // Title.
1482 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0, 1282 if (use_close_button_) {
1483 GridLayout::USE_PREF, 0, 0); // Close button 1283 header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
1484 header_cs->AddPaddingColumn( 1284 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
1485 0, ConstrainedWindowConstants::kCloseButtonPadding); 1285 GridLayout::USE_PREF, 0, 0); // Close Button.
1286 }
1486 1287
1487 views::ColumnSet* content_cs = grid_layout->AddColumnSet(CONTENT_ROW); 1288 views::ColumnSet* full_cs = grid_layout->AddColumnSet(kFullWidthColumnSet);
1488 content_cs->AddPaddingColumn( 1289 full_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1489 0, ConstrainedWindowConstants::kHorizontalPadding); 1290 GridLayout::USE_PREF, 0, 0);
1490 content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1491 GridLayout::USE_PREF, 0, 0); // Content.
1492 content_cs->AddPaddingColumn(
1493 0, ConstrainedWindowConstants::kHorizontalPadding);
1494 1291
1495 // Header. 1292 views::ColumnSet* indent_cs =
1496 grid_layout->StartRow(0, HEADER_ROW); 1293 grid_layout->AddColumnSet(kIndentedFullWidthColumnSet);
1497 if (!action_label_) 1294 indent_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
1498 action_label_ = CreateTitleLabel(); 1295 indent_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1499 action_label_->SetText(GetActionTitle()); 1296 GridLayout::USE_PREF, 0, 0);
1297
1298 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1299
1300 // Header row.
1301 grid_layout->StartRow(0, kHeaderRowColumnSet);
1302 action_label_ = new views::Label(GetActionTitle());
1303 action_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1304 action_label_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
1500 grid_layout->AddView(action_label_); 1305 grid_layout->AddView(action_label_);
1501 1306
1502 views::ImageButton* close_button = CreateCloseButton(this); 1307 if (use_close_button_)
1503 grid_layout->AddView(close_button); 1308 grid_layout->AddView(CreateCloseButton(this));
1504 close_button->SetVisible(use_close_button_);
1505 1309
1506 // Extensions. 1310 // Padding row.
1507 const int kHeaderBuiltinBottomPadding = 4; 1311 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1508 grid_layout->AddPaddingRow(0, 1312
1509 ConstrainedWindowConstants::kRowPadding - 1313 // Row with app suggestions label.
1510 kHeaderBuiltinBottomPadding); 1314 grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
1511 grid_layout->StartRow(0, CONTENT_ROW); 1315 suggestions_label_ = new views::Label();
1316 suggestions_label_->SetVisible(false);
1317 suggestions_label_->SetMultiLine(true);
1318 suggestions_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1319 grid_layout->AddView(suggestions_label_);
1320
1321 // Padding row.
1322 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1323
1324 // Row with extension suggestions.
1325 grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
1512 grid_layout->AddView(extensions_); 1326 grid_layout->AddView(extensions_);
1513 1327
1328 // Padding row.
1329 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1514 1330
1515 // Row with "more suggestions" link. 1331 // Row with "more suggestions" link.
1516 const int kIconBuiltinTopPadding = 6; 1332 grid_layout->StartRow(0, kFullWidthColumnSet);
1517 grid_layout->AddPaddingRow(0,
1518 ConstrainedWindowConstants::kRowPadding -
1519 kIconBuiltinTopPadding);
1520 grid_layout->StartRow(0, CONTENT_ROW);
1521 views::View* more_view = new views::View(); 1333 views::View* more_view = new views::View();
1522 more_view->SetLayoutManager(new views::BoxLayout( 1334 more_view->SetLayoutManager(
1523 views::BoxLayout::kHorizontal, 0, 0, kIconTextPadding)); 1335 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
1336 views::kRelatedControlHorizontalSpacing));
1524 views::ImageView* icon = new views::ImageView(); 1337 views::ImageView* icon = new views::ImageView();
1525 icon->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 1338 icon->SetImage(rb.GetImageNamed(IDR_WEBSTORE_ICON_16).ToImageSkia());
1526 IDR_WEBSTORE_ICON_16));
1527 more_view->AddChildView(icon); 1339 more_view->AddChildView(icon);
1528 if (!more_suggestions_link_) 1340 more_suggestions_link_ = new views::Link(
1529 more_suggestions_link_ = CreateLink(); 1341 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
1530 more_suggestions_link_->SetText( 1342 more_suggestions_link_->SetDisabledColor(kDisabledLinkColor);
1531 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
1532 more_suggestions_link_->set_listener(this); 1343 more_suggestions_link_->set_listener(this);
1533 more_view->AddChildView(more_suggestions_link_); 1344 more_view->AddChildView(more_suggestions_link_);
1534 grid_layout->AddView(more_view, 1, 1, 1345 grid_layout->AddView(more_view, 1, 1,
1535 GridLayout::LEADING, GridLayout::CENTER); 1346 GridLayout::LEADING, GridLayout::CENTER);
1536
1537 contents_->Layout(); 1347 contents_->Layout();
1538 } 1348 }
1539 1349
1540 void WebIntentPickerViews::ResetContents() { 1350 void WebIntentPickerViews::ResetContents() {
1541 // Abandon both web contents and webview. 1351 // Abandon both web contents and webview.
1542 webview_->SetWebContents(NULL); 1352 webview_->SetWebContents(NULL);
1543 inline_web_contents_.reset(); 1353 inline_web_contents_.reset();
1544 webview_ = NULL; 1354 webview_ = NULL;
1545 1355
1546 // Re-initialize the UI. 1356 // Re-initialize the UI.
1547 UpdateContents(); 1357 UpdateContents();
1548 1358
1549 // Restore previous state. 1359 // Restore previous state.
1550 if (extensions_) 1360 extensions_->Update();
1551 extensions_->Update(); 1361 action_label_->SetText(action_text_);
1552 if (action_label_)
1553 action_label_->SetText(action_text_);
1554 contents_->Layout(); 1362 contents_->Layout();
1555 SizeToContents(); 1363 SizeToContents();
1556 } 1364 }
1557 1365
1558 void WebIntentPickerViews::SizeToContents() { 1366 void WebIntentPickerViews::SizeToContents() {
1559 gfx::Size client_size = contents_->GetPreferredSize(); 1367 gfx::Size client_size = contents_->GetPreferredSize();
1560 gfx::Rect client_bounds(client_size); 1368 gfx::Rect client_bounds(client_size);
1561 gfx::Rect new_window_bounds = window_->non_client_view()->frame_view()-> 1369 gfx::Rect new_window_bounds = window_->non_client_view()->frame_view()->
1562 GetWindowBoundsForClientBounds(client_bounds); 1370 GetWindowBoundsForClientBounds(client_bounds);
1563 window_->CenterWindow(new_window_bounds.size()); 1371 window_->CenterWindow(new_window_bounds.size());
1564 } 1372 }
1565 1373
1566 void WebIntentPickerViews::ClearContents() { 1374 void WebIntentPickerViews::ClearContents() {
1567 DCHECK(contents_); 1375 DCHECK(contents_);
1568 // The call RemoveAllChildViews(true) deletes all children of |contents|. If 1376 // The call RemoveAllChildViews(true) deletes all children of |contents|. If
1569 // we do not set our weak pointers to NULL, then they will continue to point 1377 // we do not set our weak pointers to NULL, then they will continue to point
1570 // to where the deleted objects used to be, i.e. unitialized memory. This 1378 // to where the deleted objects used to be, i.e. unitialized memory. This
1571 // would cause hard-to-explain crashes. 1379 // would cause hard-to-explain crashes.
1572 contents_->RemoveAllChildViews(true); 1380 contents_->RemoveAllChildViews(true);
1573 action_label_ = NULL; 1381 action_label_ = NULL;
1382 suggestions_label_ = NULL;
1574 extensions_ = NULL; 1383 extensions_ = NULL;
1575 more_suggestions_link_ = NULL; 1384 more_suggestions_link_ = NULL;
1576 inline_service_icon_ = NULL;
1577 choose_another_service_link_ = NULL; 1385 choose_another_service_link_ = NULL;
1578 } 1386 }
1579
1580 void WebIntentPickerViews::RefreshInlineServiceIcon() {
1581 DCHECK(inline_service_icon_);
1582 const WebIntentPickerModel::InstalledService* inline_service =
1583 model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
1584 if (inline_service)
1585 inline_service_icon_->SetImage(inline_service->favicon.ToImageSkia());
1586 }
1587
1588 void WebIntentPickerViews::RefreshExtensions() {
1589 DCHECK(extensions_);
1590 extensions_->Update();
1591 contents_->Layout();
1592 SizeToContents();
1593 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/tab_modal_confirm_dialog_views.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698