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

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

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

Powered by Google App Engine
This is Rietveld 408576698