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

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: Move link underline into a separate CL 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.
Peter Kasting 2012/10/15 21:46:54 Nit: The
please use gerrit instead 2012/10/16 00:12:23 Done.
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 const int kLabelBuiltinTopPadding = 5;
128 const int kTopPadding = WebIntentPicker::kContentAreaBorder -
129 ConstrainedWindowConstants::kCloseButtonPadding - kLabelBuiltinTopPadding;
130 views::Label* label = CreateLabel();
131 label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
132 ui::ResourceBundle::MediumFont));
133 label->set_border(views::Border::CreateEmptyBorder(
134 kTopPadding, 0, 0, 0));
135 return label;
136 }
137
138 // Creates a link.
139 views::Link* CreateLink() {
140 views::Link* link = new views::Link();
141 link->SetEnabledColor(kEnabledLinkColor);
142 link->SetDisabledColor(kDisabledLinkColor);
143 link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
144 return link;
145 }
146
147 // Creates a header for the inline disposition dialog.
148 views::View* CreateInlineDispositionHeader(
149 views::ImageView* app_icon,
150 views::Label* app_title,
151 views::Link* use_another_service_link) {
152 const int kIconBuiltinTopPadding = 6;
153 const int kTopPadding = WebIntentPicker::kContentAreaBorder -
Peter Kasting 2012/10/15 21:46:54 Nit: Extra space
please use gerrit instead 2012/10/16 00:12:23 Removed the extra space. Good eye!
154 ConstrainedWindowConstants::kCloseButtonPadding - kIconBuiltinTopPadding;
155 views::View* header = new views::View();
156 views::GridLayout* grid_layout = new views::GridLayout(header);
157 grid_layout->SetInsets(kTopPadding, 0, 0, 0);
158 header->SetLayoutManager(grid_layout);
159 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
160 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
161 GridLayout::USE_PREF, 0, 0); // App icon.
162 header_cs->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
163 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
164 GridLayout::USE_PREF, 0, 0); // App title.
165 header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
166 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
167 GridLayout::USE_PREF, 0, 0); // Use another app link.
168 grid_layout->StartRow(0, 0);
169 grid_layout->AddView(app_icon);
170 grid_layout->AddView(app_title);
171 grid_layout->AddView(use_another_service_link);
172 header->Layout();
173 return header;
174 }
175
176 // Checks whether the inline disposition dialog should show the link for using
177 // another service.
178 bool IsUseAnotherServiceVisible(WebIntentPickerModel* model) {
179 DCHECK(model);
180 return model->show_use_another_service()
181 && (model->GetInstalledServiceCount() > 1 ||
Peter Kasting 2012/10/15 21:46:54 Nit: Operators go at end of line
please use gerrit instead 2012/10/16 00:12:23 Fixed.
182 model->GetSuggestedExtensionCount());
183 }
184
185 // StarsView -------------------------------------------------------------------
Peter Kasting 2012/10/15 21:46:54 Tiny nit: To make the eye more likely to see these
please use gerrit instead 2012/10/16 00:12:23 Done. I hope that we will split these into separat
104 186
105 // A view that displays 5 stars: empty, full or half full, given a rating in 187 // A view that displays 5 stars: empty, full or half full, given a rating in
106 // the range [0,5]. 188 // the range [0,5].
107 class StarsView : public views::View { 189 class StarsView : public views::View {
108 public: 190 public:
109 explicit StarsView(double rating); 191 explicit StarsView(double rating);
110 virtual ~StarsView(); 192 virtual ~StarsView();
111 193
112 private: 194 private:
113 // The star rating to display, in the range [0,5]. 195 // The star rating to display, in the range [0,5].
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 this_frame_ = gfx::ImageSkiaOperations::ExtractSubset(*frames_, subset_rect); 343 this_frame_ = gfx::ImageSkiaOperations::ExtractSubset(*frames_, subset_rect);
262 return this_frame_; 344 return this_frame_;
263 } 345 }
264 346
265 void ThrobberNativeTextButton::Run() { 347 void ThrobberNativeTextButton::Run() {
266 DCHECK(running_); 348 DCHECK(running_);
267 349
268 SchedulePaint(); 350 SchedulePaint();
269 } 351 }
270 352
353 // SpinnerProgressIndicator ----------------------------------------------------
354 class SpinnerProgressIndicator : public views::View {
355 public:
356 SpinnerProgressIndicator();
Peter Kasting 2012/10/15 21:46:54 Nit: I suggest adding a blank line below the const
please use gerrit instead 2012/10/16 00:12:23 Declared the virtual destructor here. Where is the
Peter Kasting 2012/10/16 00:55:06 WaitingView.
please use gerrit instead 2012/10/16 00:57:20 Done.
357 void SetPercentDone(int percent);
358 void SetIndeterminate(bool indetereminate);
359
360 // Overridden from views::View.
361 virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
362 virtual gfx::Size GetPreferredSize() OVERRIDE;
363
364 private:
365 void UpdateTimer();
366 int GetProgressAngle();
367
368 static const int kTimerIntervalMs = 1000 / 30;
369 static const int kSpinRateDegreesPerSecond = 270;
370
371 int percent_done_;
372 int indeterminate_;
373
374 base::TimeTicks start_time_;
375 base::RepeatingTimer<SpinnerProgressIndicator> timer_;
376 };
Peter Kasting 2012/10/15 21:46:54 Nit: DISALLOW_COPY_AND_ASSIGN
please use gerrit instead 2012/10/16 00:12:23 Added.
377
378 SpinnerProgressIndicator::SpinnerProgressIndicator()
379 : percent_done_(0),
Peter Kasting 2012/10/15 21:46:54 Nit: Indent 4
please use gerrit instead 2012/10/16 00:12:23 Done.
380 indeterminate_(true) {}
381
382 void SpinnerProgressIndicator::SetPercentDone(int percent) {
383 percent_done_ = percent;
384 SchedulePaint();
385 UpdateTimer();
386 }
387
388 void SpinnerProgressIndicator::SetIndeterminate(bool indetereminate) {
389 indeterminate_ = indetereminate;
390 SchedulePaint();
391 UpdateTimer();
392 }
393
394 void SpinnerProgressIndicator::Paint(gfx::Canvas* canvas) {
395 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
396 gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
397 gfx::ImageSkia* bg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_BACKGROUND);
398 download_util::PaintCustomDownloadProgress(
399 canvas,
400 *bg,
401 *fg,
402 fg->width(),
403 bounds(),
404 GetProgressAngle(),
405 indeterminate_ ? -1 : percent_done_);
406 }
407
408 gfx::Size SpinnerProgressIndicator::GetPreferredSize() {
409 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
410 gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
411 return fg->size();
412 }
413
414 void SpinnerProgressIndicator::UpdateTimer() {
415 if (!parent() || !indeterminate_) {
416 timer_.Stop();
417 return;
418 }
419
420 if (!timer_.IsRunning()) {
421 start_time_ = base::TimeTicks::Now();
422 timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimerIntervalMs),
423 this, &SpinnerProgressIndicator::SchedulePaint);
424 }
425 }
426
427 int SpinnerProgressIndicator::GetProgressAngle() {
428 if (!indeterminate_)
429 return download_util::kStartAngleDegrees;
430 base::TimeDelta delta = base::TimeTicks::Now() - start_time_;
431 int angle = delta.InSecondsF() * kSpinRateDegreesPerSecond;
432 return angle % 360;
433 }
434
271 // WaitingView ---------------------------------------------------------- 435 // WaitingView ----------------------------------------------------------
272 class WaitingView : public views::View { 436 class WaitingView : public views::View {
273 public: 437 public:
274 WaitingView(views::ButtonListener* listener, bool use_close_button); 438 WaitingView(views::ButtonListener* listener, bool use_close_button);
275 439
276 private: 440 private:
277 DISALLOW_COPY_AND_ASSIGN(WaitingView); 441 DISALLOW_COPY_AND_ASSIGN(WaitingView);
278 }; 442 };
279 443
280 WaitingView::WaitingView(views::ButtonListener* listener, 444 WaitingView::WaitingView(
281 bool use_close_button) { 445 views::ButtonListener* listener,
Peter Kasting 2012/10/15 21:46:54 Nit: Old indenting was fine
please use gerrit instead 2012/10/16 00:12:23 Returned to the old formatting style.
446 bool use_close_button) {
447
Peter Kasting 2012/10/15 21:46:54 Nit: Extra blank line
please use gerrit instead 2012/10/16 00:12:23 Removed the extra blank line.
448 views::ImageButton* close_button = CreateCloseButton(listener);
449
450 const int kThrobberTopPadding = kWaitingViewVerticalPadding -
Peter Kasting 2012/10/15 21:46:54 Nit: Don't need to declare consts/enums atop the f
please use gerrit instead 2012/10/16 00:12:23 I combed over this file to get rid of unnecessary
451 ConstrainedWindowConstants::kCloseButtonPadding -
452 close_button->GetPreferredSize().height();
453
454 const int kMessageBuiltinTopPadding = 5;
455 const int kThrobberMessagePadding = ConstrainedWindowConstants::kRowPadding -
456 kMessageBuiltinTopPadding;
457
458 const int kMessageBuiltinBottomPadding = 3;
459 const int kBottomPadding = kWaitingViewVerticalPadding -
460 kMessageBuiltinBottomPadding;
461
462 enum {
Peter Kasting 2012/10/15 21:46:54 Nit: In addition to declaring right above where it
please use gerrit instead 2012/10/16 00:12:23 Done.
463 kHeaderRow,
Peter Kasting 2012/10/15 21:46:54 Nit: Chromium style guide says to use MACRO_STYLE
please use gerrit instead 2012/10/16 00:12:23 Done.
464 kContentRow,
465 };
466
282 views::GridLayout* layout = new views::GridLayout(this); 467 views::GridLayout* layout = new views::GridLayout(this);
283 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0)); 468 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
284 layout->SetInsets(WebIntentPicker::kContentAreaBorder, 469 layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
285 WebIntentPicker::kContentAreaBorder, 470 kBottomPadding, 0);
286 WebIntentPicker::kContentAreaBorder,
287 WebIntentPicker::kContentAreaBorder);
288 SetLayoutManager(layout); 471 SetLayoutManager(layout);
289 472
290 views::ColumnSet* cs = layout->AddColumnSet(0); 473 views::ColumnSet* header_cs = layout->AddColumnSet(kHeaderRow);
291 views::ColumnSet* header_cs = NULL; 474 header_cs->AddPaddingColumn(1, 1);
292 if (use_close_button) { 475 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
293 header_cs = layout->AddColumnSet(1); 476 GridLayout::USE_PREF, 0, 0);
294 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing); 477 header_cs->AddPaddingColumn(
295 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 478 0, ConstrainedWindowConstants::kCloseButtonPadding);
296 GridLayout::USE_PREF, 0, 0); // Close Button.
297 }
298 cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
299 cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER,
300 1, GridLayout::USE_PREF, 0, 0);
301 cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
302 479
303 // Create throbber. 480 views::ColumnSet* content_cs = layout->AddColumnSet(kContentRow);
304 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 481 content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
305 const gfx::ImageSkia* frames = 482 content_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
306 rb.GetImageNamed(IDR_SPEECH_INPUT_SPINNER).ToImageSkia(); 483 GridLayout::USE_PREF, 0, 0);
307 views::Throbber* throbber = new views::Throbber(kThrobberFrameTimeMs, true); 484 content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
308 throbber->SetFrames(frames);
309 throbber->Start();
310 485
311 // Create text. 486 // Close button
312 views::Label* label = new views::Label(); 487 layout->StartRow(0, kHeaderRow);
488 layout->AddView(close_button);
489 close_button->SetVisible(use_close_button);
490
491 layout->AddPaddingRow(0, kThrobberTopPadding);
492
493 // Throbber
494 layout->StartRow(0, kContentRow);
495 SpinnerProgressIndicator* throbber = new SpinnerProgressIndicator();
496 layout->AddView(throbber);
497
498 layout->AddPaddingRow(0, kThrobberMessagePadding);
499
500 // Message
501 layout->StartRow(0, kContentRow);
502 views::Label* label = CreateLabel();
313 label->SetHorizontalAlignment(views::Label::ALIGN_CENTER); 503 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)); 504 label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
505 layout->AddView(label);
316 506
317 // Layout the view. 507 // Start the throbber.
318 if (use_close_button) { 508 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 }
331
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() {
356 }
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 } 509 }
406 510
407 // IntentRowView -------------------------------------------------- 511 // IntentRowView --------------------------------------------------
408 512
409 // A view for each row in the IntentsView. It displays information 513 // A view for each row in the IntentsView. It displays information
410 // for both installed and suggested intent handlers. 514 // for both installed and suggested intent handlers.
411 class IntentRowView : public views::View, 515 class IntentRowView : public views::View,
412 public views::ButtonListener, 516 public views::ButtonListener,
413 public views::LinkListener { 517 public views::LinkListener {
414 public: 518 public:
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 // Stop the throbber for this row, and show the star rating and the install 568 // Stop the throbber for this row, and show the star rating and the install
465 // button. 569 // button.
466 void StopThrobber(); 570 void StopThrobber();
467 571
468 protected: 572 protected:
469 virtual void OnEnabledChanged() OVERRIDE; 573 virtual void OnEnabledChanged() OVERRIDE;
470 574
471 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE; 575 virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
472 576
473 private: 577 private:
578 static const int kStarRatingHorizontalSpacing = 20;
Peter Kasting 2012/10/15 21:46:54 Nit: Does this need to be a member?
please use gerrit instead 2012/10/16 00:12:23 I moved it right next to the place where it is use
579
474 IntentRowView(ActionType type, size_t tag); 580 IntentRowView(ActionType type, size_t tag);
475 581
476 // Gets the proper message string associated with |type_|. 582 // Gets the proper message string associated with |type_|.
477 string16 GetActionButtonMessage(); 583 string16 GetActionButtonMessage();
478 584
479 // Identifier for the suggested extension displayed in this row. 585 // Identifier for the suggested extension displayed in this row.
480 std::string extension_id_; 586 std::string extension_id_;
481 587
482 // A delegate to respond to button presses and clicked links. 588 // A delegate to respond to button presses and clicked links.
483 Delegate* delegate_; 589 Delegate* delegate_;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 WebIntentPicker::kTitleLinkMaxWidth, 644 WebIntentPicker::kTitleLinkMaxWidth,
539 ui::ELIDE_AT_END); 645 ui::ELIDE_AT_END);
540 646
541 const gfx::ImageSkia* icon = NULL; 647 const gfx::ImageSkia* icon = NULL;
542 StarsView* stars = NULL; 648 StarsView* stars = NULL;
543 views::Label* label = NULL; 649 views::Label* label = NULL;
544 IntentRowView* view; 650 IntentRowView* view;
545 if (service != NULL) { 651 if (service != NULL) {
546 view = new IntentRowView(ACTION_INVOKE, tag); 652 view = new IntentRowView(ACTION_INVOKE, tag);
547 icon = service->favicon.ToImageSkia(); 653 icon = service->favicon.ToImageSkia();
548 label = new views::Label(elided_title); 654 label = CreateLabel();
655 label->SetText(elided_title);
549 } else { 656 } else {
550 view = new IntentRowView(ACTION_INSTALL, tag); 657 view = new IntentRowView(ACTION_INSTALL, tag);
551 view->extension_id_ = extension->id; 658 view->extension_id_ = extension->id;
552 icon = extension->icon.ToImageSkia(); 659 icon = extension->icon.ToImageSkia();
553 views::Link* link = new views::Link(elided_title); 660 views::Link* link = CreateLink();
661 link->SetText(elided_title);
554 link->set_listener(view); 662 link->set_listener(view);
555 label = link; 663 label = link;
556 stars = new StarsView(extension->average_rating); 664 stars = new StarsView(extension->average_rating);
557 } 665 }
558 666
559 view->delegate_ = delegate; 667 view->delegate_ = delegate;
560 668
561 view->SetLayoutManager(new SuggestedExtensionsLayout); 669 views::GridLayout* grid_layout = new views::GridLayout(view);
670 view->SetLayoutManager(grid_layout);
671
672 views::ColumnSet* columns = grid_layout->AddColumnSet(0);
673 columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
674 GridLayout::USE_PREF, 0, 0); // Icon.
675 columns->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
676 columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
677 GridLayout::FIXED, WebIntentPicker::kTitleLinkMaxWidth, 0);
678 columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
679 if (stars != NULL) {
680 columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
681 GridLayout::USE_PREF, 0, 0); // Star rating.
682 columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
683 }
684 columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
685 GridLayout::FIXED, preferred_width, 0); // Button.
686
687 grid_layout->StartRow(0, 0);
562 688
563 view->icon_ = new views::ImageView(); 689 view->icon_ = new views::ImageView();
564
565 view->icon_->SetImage(icon); 690 view->icon_->SetImage(icon);
566 view->AddChildView(view->icon_); 691 grid_layout->AddView(view->icon_);
567 692
568 view->title_link_ = label; 693 view->title_link_ = label;
569 view->AddChildView(view->title_link_); 694 grid_layout->AddView(view->title_link_);
570 695
571 if (stars != NULL) { 696 if (stars != NULL) {
572 view->stars_ = stars; 697 view->stars_ = stars;
573 view->AddChildView(view->stars_); 698 grid_layout->AddView(view->stars_);
574 } 699 }
575 700
576 view->install_button_ = new ThrobberNativeTextButton( 701 view->install_button_ = new ThrobberNativeTextButton(view,
Peter Kasting 2012/10/15 21:46:54 Nit: Old wrapping was more correct
please use gerrit instead 2012/10/16 00:12:23 Returned to the original wrapping style. Done.
577 view, view->GetActionButtonMessage()); 702 view->GetActionButtonMessage());
578 view->install_button_->set_preferred_width(preferred_width); 703 view->install_button_->set_preferred_width(preferred_width);
579 view->AddChildView(view->install_button_); 704 grid_layout->AddView(view->install_button_);
580 705
581 return view; 706 return view;
582 } 707 }
583 708
584 IntentRowView::~IntentRowView() {} 709 IntentRowView::~IntentRowView() {}
585 710
586 void IntentRowView::ButtonPressed(views::Button* sender, 711 void IntentRowView::ButtonPressed(views::Button* sender,
587 const ui::Event& event) { 712 const ui::Event& event) {
588 if (type_ == ACTION_INSTALL) 713 if (type_ == ACTION_INSTALL)
589 delegate_->OnExtensionInstallClicked(extension_id_); 714 delegate_->OnExtensionInstallClicked(extension_id_);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
695 void IntentsView::Update() { 820 void IntentsView::Update() {
696 RemoveAllChildViews(true); 821 RemoveAllChildViews(true);
697 822
698 ThrobberNativeTextButton size_helper( 823 ThrobberNativeTextButton size_helper(
699 NULL, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION)); 824 NULL, l10n_util::GetStringUTF16(IDS_INTENT_PICKER_INSTALL_EXTENSION));
700 size_helper.SetText( 825 size_helper.SetText(
701 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_SELECT_INTENT)); 826 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_SELECT_INTENT));
702 button_width_ = std::max( 827 button_width_ = std::max(
703 kButtonWidth, size_helper.GetPreferredSize().width()); 828 kButtonWidth, size_helper.GetPreferredSize().width());
704 829
705 views::BoxLayout* layout = new views::BoxLayout( 830 const int kAppRowVerticalSpacing = 10;
706 views::BoxLayout::kVertical, 0, 0, views::kRelatedControlVerticalSpacing); 831 views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical,
832 0, 0, kAppRowVerticalSpacing);
707 SetLayoutManager(layout); 833 SetLayoutManager(layout);
708 834
709 int available_rows = kMaxRowCount; 835 int available_rows = kMaxRowCount;
710 836
711 for (size_t i = 0; 837 for (size_t i = 0;
712 available_rows > 0 && i < model_->GetInstalledServiceCount(); 838 available_rows > 0 && i < model_->GetInstalledServiceCount();
713 ++i, --available_rows) { 839 ++i, --available_rows) {
714 const WebIntentPickerModel::InstalledService& service = 840 const WebIntentPickerModel::InstalledService& service =
715 model_->GetInstalledServiceAt(i); 841 model_->GetInstalledServiceAt(i);
716 AddChildView(IntentRowView::CreateHandlerRow(&service, NULL, i, 842 AddChildView(IntentRowView::CreateHandlerRow(&service, NULL, i,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 EnableChildViews(this, enabled()); 878 EnableChildViews(this, enabled());
753 View::OnEnabledChanged(); 879 View::OnEnabledChanged();
754 } 880 }
755 881
756 } // namespace 882 } // namespace
757 883
758 // WebIntentPickerViews -------------------------------------------------------- 884 // WebIntentPickerViews --------------------------------------------------------
759 885
760 // Views implementation of WebIntentPicker. 886 // Views implementation of WebIntentPicker.
761 class WebIntentPickerViews : public views::ButtonListener, 887 class WebIntentPickerViews : public views::ButtonListener,
762 public views::DialogDelegate, 888 public views::WidgetDelegate,
763 public views::LinkListener, 889 public views::LinkListener,
764 public WebIntentPicker, 890 public WebIntentPicker,
765 public WebIntentPickerModelObserver, 891 public WebIntentPickerModelObserver,
766 public IntentRowView::Delegate { 892 public IntentRowView::Delegate {
767 public: 893 public:
768 WebIntentPickerViews(TabContents* tab_contents, 894 WebIntentPickerViews(TabContents* tab_contents,
769 WebIntentPickerDelegate* delegate, 895 WebIntentPickerDelegate* delegate,
770 WebIntentPickerModel* model); 896 WebIntentPickerModel* model);
771 virtual ~WebIntentPickerViews(); 897 virtual ~WebIntentPickerViews();
772 898
773 // views::ButtonListener implementation. 899 // views::ButtonListener implementation.
774 // This method is called when the user cancels the picker dialog. 900 // This method is called when the user cancels the picker dialog.
775 virtual void ButtonPressed(views::Button* sender, 901 virtual void ButtonPressed(views::Button* sender,
776 const ui::Event& event) OVERRIDE; 902 const ui::Event& event) OVERRIDE;
777 903
778 // views::DialogDelegate implementation. 904 // views::WidgetDelegate implementation.
779 virtual void WindowClosing() OVERRIDE; 905 virtual void WindowClosing() OVERRIDE;
780 virtual void DeleteDelegate() OVERRIDE; 906 virtual void DeleteDelegate() OVERRIDE;
781 virtual views::Widget* GetWidget() OVERRIDE; 907 virtual views::Widget* GetWidget() OVERRIDE;
782 virtual const views::Widget* GetWidget() const OVERRIDE; 908 virtual const views::Widget* GetWidget() const OVERRIDE;
783 virtual views::View* GetContentsView() OVERRIDE; 909 virtual views::View* GetContentsView() OVERRIDE;
784 virtual int GetDialogButtons() const OVERRIDE;
785 virtual bool Cancel() OVERRIDE;
786 910
787 // LinkListener implementation. 911 // LinkListener implementation.
788 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; 912 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
789 913
790 // WebIntentPicker implementation. 914 // WebIntentPicker implementation.
791 virtual void Close() OVERRIDE; 915 virtual void Close() OVERRIDE;
792 virtual void SetActionString(const string16& action) OVERRIDE; 916 virtual void SetActionString(const string16& action) OVERRIDE;
793 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE; 917 virtual void OnExtensionInstallSuccess(const std::string& id) OVERRIDE;
794 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE; 918 virtual void OnExtensionInstallFailure(const std::string& id) OVERRIDE;
795 virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE; 919 virtual void OnInlineDispositionAutoResize(const gfx::Size& size) OVERRIDE;
(...skipping 14 matching lines...) Expand all
810 virtual void OnExtensionInstallClicked( 934 virtual void OnExtensionInstallClicked(
811 const std::string& extension_id) OVERRIDE; 935 const std::string& extension_id) OVERRIDE;
812 virtual void OnExtensionLinkClicked( 936 virtual void OnExtensionLinkClicked(
813 const std::string& extension_id, 937 const std::string& extension_id,
814 WindowOpenDisposition disposition) OVERRIDE; 938 WindowOpenDisposition disposition) OVERRIDE;
815 virtual void OnActionButtonClicked( 939 virtual void OnActionButtonClicked(
816 IntentRowView::ActionType type, 940 IntentRowView::ActionType type,
817 size_t tag) OVERRIDE; 941 size_t tag) OVERRIDE;
818 942
819 private: 943 private:
944 enum {
945 Initial,
946 Waiting,
947 NoServices,
948 ListServices,
949 InlineService,
950 } state_;
951
820 // Update picker contents to reflect the current state of the model. 952 // Update picker contents to reflect the current state of the model.
821 void UpdateContents(); 953 void UpdateContents();
822 954
955 // Shows a spinner and notifies the user that we are waiting for information
956 // from the Chrome Web Store.
957 void ShowWaitingForSuggestions();
958
823 // Updates the dialog with the list of available services, suggestions, 959 // 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" 960 // and a nice link to CWS to find more suggestions. This is the "Main"
825 // view of the picker. 961 // view of the picker.
826 void ShowAvailableServices(); 962 void ShowAvailableServices();
827 963
828 // Informs the user that there are no services available to handle 964 // 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. 965 // the intent, and that there are no suggestions from the Chrome Web Store.
830 void ShowNoServicesMessage(); 966 void ShowNoServicesMessage();
831 967
832 // Restore the contents of the picker to the initial contents. 968 // Restore the contents of the picker to the initial contents.
833 void ResetContents(); 969 void ResetContents();
834 970
835 // Resize the constrained window to the size of its contents. 971 // Resize the constrained window to the size of its contents.
836 void SizeToContents(); 972 void SizeToContents();
837 973
838 // Clear the contents of the picker. 974 // Clear the contents of the picker.
839 void ClearContents(); 975 void ClearContents();
840 976
841 // Returns the service selection question text used in the title 977 // Returns the service selection question text used in the title
842 // of the picker. 978 // of the picker.
843 const string16 GetActionTitle(); 979 const string16 GetActionTitle();
844 980
981 // Refresh the icon for the inline disposition service that is being
982 // displayed.
983 void RefreshInlineServiceIcon();
984
845 // A weak pointer to the WebIntentPickerDelegate to notify when the user 985 // A weak pointer to the WebIntentPickerDelegate to notify when the user
846 // chooses a service or cancels. 986 // chooses a service or cancels.
847 WebIntentPickerDelegate* delegate_; 987 WebIntentPickerDelegate* delegate_;
848 988
849 // A weak pointer to the picker model. 989 // A weak pointer to the picker model.
850 WebIntentPickerModel* model_; 990 WebIntentPickerModel* model_;
851 991
852 // A weak pointer to the action string label. 992 // A weak pointer to the action string label.
853 // Created locally, owned by Views. 993 // Created locally, owned by Views.
854 views::Label* action_label_; 994 views::Label* action_label_;
855 995
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. 996 // A weak pointer to the intents view.
861 // Created locally, owned by Views view hierarchy. 997 // Created locally, owned by Views view hierarchy.
862 IntentsView* extensions_; 998 IntentsView* extensions_;
863 999
864 // Delegate for inline disposition tab contents. 1000 // Delegate for inline disposition tab contents.
865 scoped_ptr<WebIntentInlineDispositionDelegate> inline_disposition_delegate_; 1001 scoped_ptr<WebIntentInlineDispositionDelegate> inline_disposition_delegate_;
866 1002
867 // A weak pointer to the TabContents this picker is in. 1003 // A weak pointer to the TabContents this picker is in.
868 TabContents* tab_contents_; 1004 TabContents* tab_contents_;
869 1005
870 // A weak pointer to the WebView that hosts the WebContents being displayed. 1006 // A weak pointer to the WebView that hosts the WebContents being displayed.
871 // Created locally, owned by Views. 1007 // Created locally, owned by Views.
872 views::WebView* webview_; 1008 views::WebView* webview_;
873 1009
874 // A weak pointer to the view that contains all other views in the picker. 1010 // A weak pointer to the view that contains all other views in the picker.
875 // Created locally, owned by Views. 1011 // Created locally, owned by Views.
876 views::View* contents_; 1012 views::View* contents_;
877 1013
878 // A weak pointer to the constrained window. 1014 // A weak pointer to the constrained window.
879 // Created locally, owned by Views. 1015 // Created locally, owned by Views.
880 ConstrainedWindowViews* window_; 1016 ConstrainedWindowViews* window_;
881 1017
882 // A weak pointer to the more suggestions link. 1018 // A weak pointer to the more suggestions link.
883 // Created locally, owned by Views. 1019 // Created locally, owned by Views.
884 views::Link* more_suggestions_link_; 1020 views::Link* more_suggestions_link_;
885 1021
1022 // The icon for the inline disposition service.
1023 views::ImageView* inline_service_icon_;
1024
886 // A weak pointer to the choose another service link. 1025 // A weak pointer to the choose another service link.
887 // Created locally, owned by Views. 1026 // Created locally, owned by Views.
888 views::Link* choose_another_service_link_; 1027 views::Link* choose_another_service_link_;
889 1028
890 // Weak pointer to "Waiting for CWS" display. Owned by parent view. 1029 // Weak pointer to "Waiting for CWS" display. Owned by parent view.
891 WaitingView* waiting_view_; 1030 WaitingView* waiting_view_;
892 1031
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. 1032 // The text for the current action.
898 string16 action_text_; 1033 string16 action_text_;
899 1034
900 // Ownership of the WebContents we are displaying in the inline disposition. 1035 // Ownership of the WebContents we are displaying in the inline disposition.
901 scoped_ptr<WebContents> inline_web_contents_; 1036 scoped_ptr<WebContents> inline_web_contents_;
902 1037
903 // Indicate if dialog should display its own close button. 1038 // Indicate if dialog should display its own close button.
904 // TODO(groby): Only relevant until new ConstrainedWindow is implemented, 1039 // TODO(groby): Only relevant until new ConstrainedWindow is implemented,
905 // from then on always true. 1040 // from then on always true.
906 bool use_close_button_; 1041 bool use_close_button_;
907 1042
908 // Signals if the picker can be closed. False during extension install. 1043 // Signals if the picker can be closed. False during extension install.
909 bool can_close_; 1044 bool can_close_;
910 1045
911 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews); 1046 DISALLOW_COPY_AND_ASSIGN(WebIntentPickerViews);
912 }; 1047 };
913 1048
914 // static 1049 // static
915 WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents, 1050 WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents,
916 WebIntentPickerDelegate* delegate, 1051 WebIntentPickerDelegate* delegate,
917 WebIntentPickerModel* model) { 1052 WebIntentPickerModel* model) {
918 TabContents* tab_contents = TabContents::FromWebContents(web_contents); 1053 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
919 return new WebIntentPickerViews(tab_contents, delegate, model); 1054 return new WebIntentPickerViews(tab_contents, delegate, model);
920 } 1055 }
921 1056
922 WebIntentPickerViews::WebIntentPickerViews(TabContents* tab_contents, 1057 WebIntentPickerViews::WebIntentPickerViews(TabContents* tab_contents,
923 WebIntentPickerDelegate* delegate, 1058 WebIntentPickerDelegate* delegate,
924 WebIntentPickerModel* model) 1059 WebIntentPickerModel* model)
925 : delegate_(delegate), 1060 : state_(Initial),
1061 delegate_(delegate),
926 model_(model), 1062 model_(model),
927 action_label_(NULL), 1063 action_label_(NULL),
928 suggestions_label_(NULL),
929 extensions_(NULL), 1064 extensions_(NULL),
930 tab_contents_(tab_contents), 1065 tab_contents_(tab_contents),
931 webview_(new views::WebView(tab_contents->profile())), 1066 webview_(new views::WebView(tab_contents->profile())),
932 window_(NULL), 1067 window_(NULL),
933 more_suggestions_link_(NULL), 1068 more_suggestions_link_(NULL),
1069 inline_service_icon_(NULL),
934 choose_another_service_link_(NULL), 1070 choose_another_service_link_(NULL),
935 waiting_view_(NULL), 1071 waiting_view_(NULL),
936 displaying_web_contents_(false),
937 can_close_(true) { 1072 can_close_(true) {
938 bool enable_chrome_style = chrome::IsFramelessConstrainedDialogEnabled(); 1073 bool enable_chrome_style = chrome::IsFramelessConstrainedDialogEnabled();
939 use_close_button_ = enable_chrome_style; 1074 use_close_button_ = enable_chrome_style;
940 1075
941 model_->set_observer(this); 1076 model_->set_observer(this);
942 contents_ = new views::View(); 1077 contents_ = new views::View();
1078 contents_->set_background(views::Background::CreateSolidBackground(
1079 ConstrainedWindow::GetBackgroundColor()));
1080
943 // Show the dialog. 1081 // Show the dialog.
944 window_ = new ConstrainedWindowViews(tab_contents->web_contents(), 1082 window_ = new ConstrainedWindowViews(tab_contents->web_contents(), this,
945 this, 1083 enable_chrome_style, gfx::Insets());
946 enable_chrome_style);
947
948 UpdateContents(); 1084 UpdateContents();
949 } 1085 }
950 1086
951 WebIntentPickerViews::~WebIntentPickerViews() { 1087 WebIntentPickerViews::~WebIntentPickerViews() {
952 model_->set_observer(NULL); 1088 model_->set_observer(NULL);
953 } 1089 }
954 1090
955 void WebIntentPickerViews::ButtonPressed(views::Button* sender, 1091 void WebIntentPickerViews::ButtonPressed(views::Button* sender,
956 const ui::Event& event) { 1092 const ui::Event& event) {
957 delegate_->OnUserCancelledPickerDialog(); 1093 delegate_->OnUserCancelledPickerDialog();
(...skipping 12 matching lines...) Expand all
970 } 1106 }
971 1107
972 const views::Widget* WebIntentPickerViews::GetWidget() const { 1108 const views::Widget* WebIntentPickerViews::GetWidget() const {
973 return contents_->GetWidget(); 1109 return contents_->GetWidget();
974 } 1110 }
975 1111
976 views::View* WebIntentPickerViews::GetContentsView() { 1112 views::View* WebIntentPickerViews::GetContentsView() {
977 return contents_; 1113 return contents_;
978 } 1114 }
979 1115
980 int WebIntentPickerViews::GetDialogButtons() const {
981 return ui::DIALOG_BUTTON_NONE;
982 }
983
984 bool WebIntentPickerViews::Cancel() {
985 return can_close_;
986 }
987
988 void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) { 1116 void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) {
989 if (source == more_suggestions_link_) { 1117 if (source == more_suggestions_link_) {
990 delegate_->OnSuggestionsLinkClicked( 1118 delegate_->OnSuggestionsLinkClicked(
991 chrome::DispositionFromEventFlags(event_flags)); 1119 chrome::DispositionFromEventFlags(event_flags));
992 } else if (source == choose_another_service_link_) { 1120 } else if (source == choose_another_service_link_) {
993 // Signal cancellation of inline disposition. 1121 // Signal cancellation of inline disposition.
994 delegate_->OnChooseAnotherService(); 1122 delegate_->OnChooseAnotherService();
995 ResetContents(); 1123 ResetContents();
996 } else { 1124 } else {
997 NOTREACHED(); 1125 NOTREACHED();
998 } 1126 }
999 } 1127 }
1000 1128
1001 void WebIntentPickerViews::Close() { 1129 void WebIntentPickerViews::Close() {
1002 window_->CloseConstrainedWindow(); 1130 window_->CloseConstrainedWindow();
1003 } 1131 }
1004 1132
1005 void WebIntentPickerViews::SetActionString(const string16& action) { 1133 void WebIntentPickerViews::SetActionString(const string16& action) {
1006 action_text_ = action; 1134 action_text_ = action;
1007 1135 if (action_label_) {
1008 if (action_label_)
1009 action_label_->SetText(GetActionTitle()); 1136 action_label_->SetText(GetActionTitle());
1010 contents_->Layout(); 1137 contents_->Layout();
1011 SizeToContents(); 1138 SizeToContents();
1139 }
1012 } 1140 }
1013 1141
1014 void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) { 1142 void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) {
1015 can_close_ = true; 1143 can_close_ = true;
1016 } 1144 }
1017 1145
1018 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) { 1146 void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) {
1019 extensions_->StopThrobber(); 1147 extensions_->StopThrobber();
1148 extensions_->SetEnabled(true);
1020 more_suggestions_link_->SetEnabled(true); 1149 more_suggestions_link_->SetEnabled(true);
1021 can_close_ = true; 1150 can_close_ = true;
1022 contents_->Layout(); 1151 contents_->Layout();
1023 SizeToContents(); 1152 SizeToContents();
1024 1153
1025 // TODO(binji): What to display to user on failure? 1154 // TODO(binji): What to display to user on failure?
1026 } 1155 }
1027 1156
1028 void WebIntentPickerViews::OnInlineDispositionAutoResize( 1157 void WebIntentPickerViews::OnInlineDispositionAutoResize(
1029 const gfx::Size& size) { 1158 const gfx::Size& size) {
1030 webview_->SetPreferredSize(size); 1159 webview_->SetPreferredSize(size);
1031 contents_->Layout(); 1160 contents_->Layout();
1032 SizeToContents(); 1161 SizeToContents();
1033 } 1162 }
1034 1163
1035 void WebIntentPickerViews::OnPendingAsyncCompleted() { 1164 void WebIntentPickerViews::OnPendingAsyncCompleted() {
1036 UpdateContents(); 1165 UpdateContents();
1037 } 1166 }
1038 1167
1039 void WebIntentPickerViews::ShowNoServicesMessage() { 1168 void WebIntentPickerViews::ShowNoServicesMessage() {
1169 const int kHeaderBuiltinBottomPadding = 4;
1170 const int kContentBuiltinTopPadding = 5;
1171 const int kHeaderContentPadding = ConstrainedWindowConstants::kRowPadding -
1172 kHeaderBuiltinBottomPadding - kContentBuiltinTopPadding;
1173
1174 const int kContentBuiltinBottomPadding = 3;
1175 const int kContentBottomPadding =
1176 ConstrainedWindowConstants::kClientBottomPadding -
1177 kContentBuiltinBottomPadding;
1178
1179 enum {
1180 kHeaderRow,
1181 kContentRow,
1182 };
1183
1184 if (state_ == NoServices)
1185 return;
1186 state_ = NoServices;
1187
1040 ClearContents(); 1188 ClearContents();
1041 1189 views::GridLayout* layout = new views::GridLayout(contents_);
1042 views::GridLayout* grid_layout = new views::GridLayout(contents_); 1190 layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
1043 contents_->SetLayoutManager(grid_layout); 1191 layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
1044 1192 kContentBottomPadding, 0);
1045 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder, 1193 contents_->SetLayoutManager(layout);
1046 kContentAreaBorder, kContentAreaBorder); 1194
1047 views::ColumnSet* main_cs = grid_layout->AddColumnSet(0); 1195 views::ColumnSet* header_cs = layout->AddColumnSet(kHeaderRow);
1048 main_cs->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1, 1196 header_cs->AddPaddingColumn(
1049 GridLayout::USE_PREF, 0, 0); 1197 0, ConstrainedWindowConstants::kHorizontalPadding);
1050 1198 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
1051 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1199 GridLayout::USE_PREF, 0, 0); // Title
1052 1200 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
1053 grid_layout->StartRow(0, 0); 1201 GridLayout::USE_PREF, 0, 0); // Close button
1054 views::Label* header = new views::Label(); 1202 header_cs->AddPaddingColumn(
1055 header->SetHorizontalAlignment(views::Label::ALIGN_LEFT); 1203 0, ConstrainedWindowConstants::kCloseButtonPadding);
1056 header->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont)); 1204
1057 header->SetText(l10n_util::GetStringUTF16( 1205 views::ColumnSet* content_cs = layout->AddColumnSet(kContentRow);
1206 content_cs->AddPaddingColumn(
1207 0, ConstrainedWindowConstants::kHorizontalPadding);
1208 content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1209 GridLayout::USE_PREF, 0, 0); // Body
1210 content_cs->AddPaddingColumn(
1211 0, ConstrainedWindowConstants::kHorizontalPadding);
1212
1213 // Header
1214 layout->StartRow(0, kHeaderRow);
1215 views::Label* title = CreateTitleLabel();
1216 title->SetText(l10n_util::GetStringUTF16(
1058 IDS_INTENT_PICKER_NO_SERVICES_TITLE)); 1217 IDS_INTENT_PICKER_NO_SERVICES_TITLE));
1059 grid_layout->AddView(header); 1218 layout->AddView(title);
1060 1219
1061 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 1220 views::ImageButton* close_button = CreateCloseButton(this);
1062 1221 layout->AddView(close_button);
1063 grid_layout->StartRow(0, 0); 1222 close_button->SetVisible(use_close_button_);
1064 views::Label* body = new views::Label(); 1223
1224 // Padding
1225 layout->AddPaddingRow(0, kHeaderContentPadding);
1226
1227 // Content
1228 layout->StartRow(0, kContentRow);
1229 views::Label* body = CreateLabel();
1065 body->SetMultiLine(true); 1230 body->SetMultiLine(true);
1066 body->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1067 body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES)); 1231 body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES));
1068 grid_layout->AddView(body); 1232 layout->AddView(body);
1069 1233
1070 int height = contents_->GetHeightForWidth(kWindowMinWidth); 1234 int height = contents_->GetHeightForWidth(WebIntentPicker::kWindowMinWidth);
1071 contents_->SetSize(gfx::Size(kWindowMinWidth, height)); 1235 contents_->SetSize(gfx::Size(WebIntentPicker::kWindowMinWidth, height));
1236 contents_->Layout();
1072 } 1237 }
1073 1238
1074 void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded( 1239 void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded(
1075 content::WebContents* web_contents) { 1240 content::WebContents* web_contents) {
1076 if (displaying_web_contents_) 1241 const int kHeaderBuiltinBottomPadding = 4;
1242 const int kSeparatorTopPadding = ConstrainedWindowConstants::kRowPadding -
1243 kHeaderBuiltinBottomPadding;
1244
1245 const int kSeparatorBottomPadding = 3;
1246
1247 enum {
1248 kHeaderRow,
1249 kSeparatorRow,
1250 kWebContentsRow,
1251 };
1252
1253 if (state_ == InlineService)
1077 return; 1254 return;
1255 state_ = InlineService;
1078 1256
1079 // Replace the picker with the inline disposition. 1257 // Replace the picker with the inline disposition.
1080 ClearContents(); 1258 ClearContents();
1081
1082 views::GridLayout* grid_layout = new views::GridLayout(contents_); 1259 views::GridLayout* grid_layout = new views::GridLayout(contents_);
1260 grid_layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
1261 grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
1262 ConstrainedWindowConstants::kClientBottomPadding, 0);
1083 contents_->SetLayoutManager(grid_layout); 1263 contents_->SetLayoutManager(grid_layout);
1084 1264
1085 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder, 1265 views::ColumnSet* header_cs = grid_layout->AddColumnSet(kHeaderRow);
1086 kContentAreaBorder, kContentAreaBorder); 1266 header_cs->AddPaddingColumn(
1087 views::ColumnSet* header_cs = grid_layout->AddColumnSet(0); 1267 0, ConstrainedWindowConstants::kHorizontalPadding);
1088 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 1268 header_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1089 GridLayout::USE_PREF, 0, 0); // Icon. 1269 GridLayout::USE_PREF, 0, 0); // Icon, title, link.
1090 header_cs->AddPaddingColumn(0, 4); 1270 header_cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
1091 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 1271 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
1092 GridLayout::USE_PREF, 0, 0); // Title. 1272 GridLayout::USE_PREF, 0, 0); // Close button.
1093 header_cs->AddPaddingColumn(0, 4); 1273 header_cs->AddPaddingColumn(
1094 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 1274 0, ConstrainedWindowConstants::kCloseButtonPadding);
1095 GridLayout::USE_PREF, 0, 0); // Link. 1275
1096 header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing); 1276 views::ColumnSet* sep_cs = grid_layout->AddColumnSet(kSeparatorRow);
1097 if (use_close_button_) { 1277 sep_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1098 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 1278 GridLayout::USE_PREF, 0, 0); // Separator.
1099 GridLayout::USE_PREF, 0, 0); // Close Button. 1279
1100 } 1280 views::ColumnSet* contents_cs = grid_layout->AddColumnSet(kWebContentsRow);
1101 1281 contents_cs->AddPaddingColumn(0, 1);
1102 views::ColumnSet* full_cs = grid_layout->AddColumnSet(1); 1282 contents_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
1103 full_cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0, 1283 GridLayout::USE_PREF, 0, 0); // Web contents.
1104 GridLayout::USE_PREF, 0, 0); 1284 contents_cs->AddPaddingColumn(0, 1);
1285
1286 // Header.
1287 grid_layout->StartRow(0, kHeaderRow);
1105 1288
1106 const WebIntentPickerModel::InstalledService* service = 1289 const WebIntentPickerModel::InstalledService* service =
1107 model_->GetInstalledServiceWithURL(model_->inline_disposition_url()); 1290 model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
1108 1291
1109 // Header row. 1292 if (!inline_service_icon_)
1110 grid_layout->StartRow(0, 0); 1293 inline_service_icon_ = new views::ImageView();
1111 views::ImageView* icon = new views::ImageView(); 1294 inline_service_icon_->SetImage(service->favicon.ToImageSkia());
1112 icon->SetImage(service->favicon.ToImageSkia()); 1295
1113 grid_layout->AddView(icon); 1296 views::Label* title = CreateLabel();
1114 1297 title->SetText(ui::ElideText(
1115 string16 elided_title = ui::ElideText( 1298 service->title, title->font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END));
1116 service->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END); 1299
1117 views::Label* title = new views::Label(elided_title); 1300 if (!choose_another_service_link_)
1118 grid_layout->AddView(title); 1301 choose_another_service_link_ = CreateLink();
1119 // Add link for "choose another service" if other suggestions are available 1302 choose_another_service_link_->SetText(l10n_util::GetStringUTF16(
1120 // or if more than one (the current) service is installed. 1303 IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
1121 if (model_->GetInstalledServiceCount() > 1 || 1304 choose_another_service_link_->set_listener(this);
1122 model_->GetSuggestedExtensionCount()) { 1305
1123 choose_another_service_link_ = new views::Link( 1306 grid_layout->AddView(CreateInlineDispositionHeader(
1124 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE)); 1307 inline_service_icon_, title, choose_another_service_link_));
1125 grid_layout->AddView(choose_another_service_link_); 1308 choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model_));
1126 choose_another_service_link_->set_listener(this); 1309
1127 } 1310 views::ImageButton* close_button = CreateCloseButton(this);
1128 1311 grid_layout->AddView(close_button);
1129 if (use_close_button_) 1312 close_button->SetVisible(use_close_button_);
1130 grid_layout->AddView(CreateCloseButton(this)); 1313
1131 1314 // Padding.
Peter Kasting 2012/10/15 21:46:54 Nit: I'd probably just put the AddPaddingRow() ato
please use gerrit instead 2012/10/16 00:12:23 I combed through the file and moved the AddPadding
1132 // Inline web contents row. 1315 grid_layout->AddPaddingRow(0, kSeparatorTopPadding);
1133 grid_layout->StartRow(0, 1); 1316
1134 grid_layout->AddView(webview_, 1, 1, GridLayout::CENTER, 1317 // Separator.
1135 GridLayout::CENTER, 0, 0); 1318 grid_layout->StartRow(0, kSeparatorRow);
1319 grid_layout->AddView(new views::Separator());
1320
1321 // Padding.
1322 grid_layout->AddPaddingRow(0, kSeparatorBottomPadding);
1323
1324 // Inline web contents.
1325 grid_layout->StartRow(0, kWebContentsRow);
1326 grid_layout->AddView(webview_);
1327
1136 contents_->Layout(); 1328 contents_->Layout();
1137 SizeToContents(); 1329 SizeToContents();
1138 displaying_web_contents_ = true;
1139 } 1330 }
1140 1331
1141 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) { 1332 void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
1142 if (waiting_view_ && !model->IsWaitingForSuggestions()) 1333 if (state_ == Waiting && !model->IsWaitingForSuggestions())
1143 UpdateContents(); 1334 UpdateContents();
1144 1335
1145 if (suggestions_label_) { 1336 if (choose_another_service_link_) {
1146 string16 label_text = model->GetSuggestionsLinkText(); 1337 choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model));
1147 suggestions_label_->SetText(label_text); 1338 contents_->Layout();
1148 suggestions_label_->SetVisible(!label_text.empty()); 1339 SizeToContents();
1149 } 1340 }
1150 1341
1151 if (extensions_) 1342 if (extensions_) {
Peter Kasting 2012/10/15 21:46:54 Nit: This block also appears below. Consider whet
please use gerrit instead 2012/10/16 00:12:23 Moved this block into WebIntentPickerViews::Refres
1152 extensions_->Update(); 1343 extensions_->Update();
1153 contents_->Layout(); 1344 contents_->Layout();
1154 SizeToContents(); 1345 SizeToContents();
1346 }
1155 } 1347 }
1156 1348
1157 void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model, 1349 void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model,
1158 size_t index) { 1350 size_t index) {
1159 // TODO(groby): Update favicons on extensions_; 1351 // TODO(groby): Update favicons on extensions_;
1160 contents_->Layout(); 1352 if (inline_service_icon_)
1161 SizeToContents(); 1353 RefreshInlineServiceIcon();
1354 if (extensions_) {
1355 extensions_->Update();
1356 contents_->Layout();
1357 SizeToContents();
1358 }
1162 } 1359 }
1163 1360
1164 void WebIntentPickerViews::OnExtensionIconChanged( 1361 void WebIntentPickerViews::OnExtensionIconChanged(
1165 WebIntentPickerModel* model, 1362 WebIntentPickerModel* model,
1166 const std::string& extension_id) { 1363 const std::string& extension_id) {
1167 if (extensions_) 1364 if (inline_service_icon_)
Peter Kasting 2012/10/15 21:46:54 Nit: The contents of this fucntion and OnFaviconCh
please use gerrit instead 2012/10/16 00:12:23 Done.
1365 RefreshInlineServiceIcon();
1366 if (extensions_) {
1168 extensions_->Update(); 1367 extensions_->Update();
1169 1368 contents_->Layout();
1170 contents_->Layout(); 1369 SizeToContents();
1171 SizeToContents(); 1370 }
1172 } 1371 }
1173 1372
1174 void WebIntentPickerViews::OnInlineDisposition( 1373 void WebIntentPickerViews::OnInlineDisposition(
1175 const string16&, const GURL& url) { 1374 const string16&, const GURL& url) {
1176 if (!webview_) 1375 if (!webview_)
1177 webview_ = new views::WebView(tab_contents_->profile()); 1376 webview_ = new views::WebView(tab_contents_->profile());
1178 1377
1179 inline_web_contents_.reset(delegate_->CreateWebContentsForInlineDisposition( 1378 inline_web_contents_.reset(delegate_->CreateWebContentsForInlineDisposition(
1180 tab_contents_->profile(), url)); 1379 tab_contents_->profile(), url));
1181 // Does not take ownership, so we keep a scoped_ptr 1380 // Does not take ownership, so we keep a scoped_ptr
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 IntentRowView::ActionType type, size_t tag) { 1418 IntentRowView::ActionType type, size_t tag) {
1220 DCHECK_EQ(IntentRowView::ACTION_INVOKE, type); 1419 DCHECK_EQ(IntentRowView::ACTION_INVOKE, type);
1221 const WebIntentPickerModel::InstalledService& service = 1420 const WebIntentPickerModel::InstalledService& service =
1222 model_->GetInstalledServiceAt(tag); 1421 model_->GetInstalledServiceAt(tag);
1223 delegate_->OnServiceChosen(service.url, service.disposition, 1422 delegate_->OnServiceChosen(service.url, service.disposition,
1224 WebIntentPickerDelegate::kEnableDefaults); 1423 WebIntentPickerDelegate::kEnableDefaults);
1225 } 1424 }
1226 1425
1227 void WebIntentPickerViews::UpdateContents() { 1426 void WebIntentPickerViews::UpdateContents() {
1228 if (model_ && model_->IsWaitingForSuggestions()) { 1427 if (model_ && model_->IsWaitingForSuggestions()) {
1229 ClearContents(); 1428 ShowWaitingForSuggestions();
1230 contents_->SetLayoutManager(new views::FillLayout());
1231 waiting_view_ = new WaitingView(this, use_close_button_);
1232 contents_->AddChildView(waiting_view_);
1233 int height = contents_->GetHeightForWidth(kWindowMinWidth);
1234 contents_->SetSize(gfx::Size(kWindowMinWidth, height));
1235 contents_->Layout();
1236 } else if (model_->GetInstalledServiceCount() || 1429 } else if (model_->GetInstalledServiceCount() ||
1237 model_->GetSuggestedExtensionCount()) { 1430 model_->GetSuggestedExtensionCount()) {
1238 ShowAvailableServices(); 1431 ShowAvailableServices();
1239 } else { 1432 } else {
1240 ShowNoServicesMessage(); 1433 ShowNoServicesMessage();
1241 } 1434 }
1242 SizeToContents(); 1435 SizeToContents();
1243 } 1436 }
1244 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
1245 const string16 WebIntentPickerViews::GetActionTitle() { 1451 const string16 WebIntentPickerViews::GetActionTitle() {
1246 return (!action_text_.empty()) ? 1452 return (!action_text_.empty()) ? action_text_ :
Peter Kasting 2012/10/15 21:46:54 Nit: No parens around unary expression. Also cons
please use gerrit instead 2012/10/16 00:12:23 Done.
1247 action_text_ :
1248 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE); 1453 l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE);
1249 } 1454 }
1250 1455
1251 void WebIntentPickerViews::ShowAvailableServices() { 1456 void WebIntentPickerViews::ShowAvailableServices() {
1457 const int kHeaderBuiltinBottomPadding = 4;
1458 const int kHeaderExtensionsPadding = ConstrainedWindowConstants::kRowPadding -
1459 kHeaderBuiltinBottomPadding;
1460
1461 const int kIconBuiltinTopPadding = 6;
1462 const int kExtensionsSuggestionsPadding =
1463 ConstrainedWindowConstants::kRowPadding - kIconBuiltinTopPadding;
1464
1465 const int kIconBuiltinBottomPadding = 4;
1466 const int kBottomPadding = ConstrainedWindowConstants::kClientBottomPadding -
1467 kIconBuiltinBottomPadding;
1468
1252 enum { 1469 enum {
1253 kHeaderRowColumnSet, // Column set for header layout. 1470 kHeaderRow,
1254 kFullWidthColumnSet, // Column set with a single full-width column. 1471 kContentRow,
1255 kIndentedFullWidthColumnSet, // Single full-width column, indented.
1256 }; 1472 };
1257 1473
1258 ClearContents(); 1474 ClearContents();
1259 displaying_web_contents_ = false; 1475 state_ = ListServices;
1260
1261 extensions_ = new IntentsView(model_, this); 1476 extensions_ = new IntentsView(model_, this);
1477 gfx::Size min_size = gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0);
1262 1478
1263 views::GridLayout* grid_layout = new views::GridLayout(contents_); 1479 views::GridLayout* grid_layout = new views::GridLayout(contents_);
1480 grid_layout->set_minimum_size(min_size);
1481 grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
1482 kBottomPadding, 0);
1264 contents_->SetLayoutManager(grid_layout); 1483 contents_->SetLayoutManager(grid_layout);
1265 1484
1266 grid_layout->set_minimum_size( 1485 views::ColumnSet* header_cs = grid_layout->AddColumnSet(kHeaderRow);
1267 gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0)); 1486 header_cs->AddPaddingColumn(
1268 grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder, 1487 0, ConstrainedWindowConstants::kHorizontalPadding);
1269 kContentAreaBorder, kContentAreaBorder);
1270 views::ColumnSet* header_cs = grid_layout->AddColumnSet(kHeaderRowColumnSet);
1271 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1, 1488 header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
1272 GridLayout::USE_PREF, 0, 0); // Title. 1489 GridLayout::USE_PREF, 0, 0); // Action title
1273 if (use_close_button_) { 1490 header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
1274 header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing); 1491 GridLayout::USE_PREF, 0, 0); // Close button
1275 header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0, 1492 header_cs->AddPaddingColumn(
1276 GridLayout::USE_PREF, 0, 0); // Close Button. 1493 0, ConstrainedWindowConstants::kCloseButtonPadding);
1277 }
1278 1494
1279 views::ColumnSet* full_cs = grid_layout->AddColumnSet(kFullWidthColumnSet); 1495 views::ColumnSet* content_cs = grid_layout->AddColumnSet(kContentRow);
1280 full_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, 1496 content_cs->AddPaddingColumn(
1281 GridLayout::USE_PREF, 0, 0); 1497 0, ConstrainedWindowConstants::kHorizontalPadding);
1498 content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
1499 GridLayout::USE_PREF, 0, 0); // Content.
1500 content_cs->AddPaddingColumn(
1501 0, ConstrainedWindowConstants::kHorizontalPadding);
1282 1502
1283 views::ColumnSet* indent_cs = 1503 // Header.
1284 grid_layout->AddColumnSet(kIndentedFullWidthColumnSet); 1504 grid_layout->StartRow(0, kHeaderRow);
1285 indent_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing); 1505 if (!action_label_)
1286 indent_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1, 1506 action_label_ = CreateTitleLabel();
1287 GridLayout::USE_PREF, 0, 0); 1507 action_label_->SetText(GetActionTitle());
1508 grid_layout->AddView(action_label_);
1509
1510 views::ImageButton* close_button = CreateCloseButton(this);
1511 grid_layout->AddView(close_button);
1512 close_button->SetVisible(use_close_button_);
1513
1514 // Padding.
1515 grid_layout->AddPaddingRow(0, kHeaderExtensionsPadding);
1516
1517 // Extensions.
1518 grid_layout->StartRow(0, kContentRow);
1519 grid_layout->AddView(extensions_);
1520
1521 // Padding.
1522 grid_layout->AddPaddingRow(0, kExtensionsSuggestionsPadding);
1288 1523
1289 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1524 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
Peter Kasting 2012/10/15 21:46:54 Nit: Consider inlining into use below
please use gerrit instead 2012/10/16 00:12:23 Done.
1290 1525
1291 // Header row.
1292 grid_layout->StartRow(0, kHeaderRowColumnSet);
1293 action_label_ = new views::Label(GetActionTitle());
1294 action_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1295 action_label_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
1296 grid_layout->AddView(action_label_);
1297
1298 if (use_close_button_)
1299 grid_layout->AddView(CreateCloseButton(this));
1300
1301 // Padding row.
1302 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1303
1304 // Row with app suggestions label.
1305 grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
1306 suggestions_label_ = new views::Label();
1307 suggestions_label_->SetVisible(false);
1308 suggestions_label_->SetMultiLine(true);
1309 suggestions_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
1310 grid_layout->AddView(suggestions_label_);
1311
1312 // Padding row.
1313 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1314
1315 // Row with extension suggestions.
1316 grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
1317 grid_layout->AddView(extensions_);
1318
1319 // Padding row.
1320 grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
1321
1322 // Row with "more suggestions" link. 1526 // Row with "more suggestions" link.
1323 grid_layout->StartRow(0, kFullWidthColumnSet); 1527 grid_layout->StartRow(0, kContentRow);
1324 views::View* more_view = new views::View(); 1528 views::View* more_view = new views::View();
1325 more_view->SetLayoutManager( 1529 more_view->SetLayoutManager(
1326 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1530 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
1327 views::kRelatedControlHorizontalSpacing)); 1531 kIconTextPadding));
Peter Kasting 2012/10/15 21:46:54 Nit: Or wrap as more_view->SetLayoutManager(new
please use gerrit instead 2012/10/16 00:12:23 Done.
1328 views::ImageView* icon = new views::ImageView(); 1532 views::ImageView* icon = new views::ImageView();
1329 icon->SetImage(rb.GetImageNamed(IDR_WEBSTORE_ICON_16).ToImageSkia()); 1533 icon->SetImage(rb.GetImageNamed(IDR_WEBSTORE_ICON_16).ToImageSkia());
1330 more_view->AddChildView(icon); 1534 more_view->AddChildView(icon);
1331 more_suggestions_link_ = new views::Link( 1535 if (!more_suggestions_link_)
1332 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE)); 1536 more_suggestions_link_ = CreateLink();
1333 more_suggestions_link_->SetDisabledColor(kDisabledLinkColor); 1537 more_suggestions_link_->SetText(
1538 l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
1334 more_suggestions_link_->set_listener(this); 1539 more_suggestions_link_->set_listener(this);
1335 more_view->AddChildView(more_suggestions_link_); 1540 more_view->AddChildView(more_suggestions_link_);
1336 grid_layout->AddView(more_view, 1, 1, 1541 grid_layout->AddView(more_view, 1, 1,
1337 GridLayout::LEADING, GridLayout::CENTER); 1542 GridLayout::LEADING, GridLayout::CENTER);
1543
1338 contents_->Layout(); 1544 contents_->Layout();
1339 } 1545 }
1340 1546
1341 void WebIntentPickerViews::ResetContents() { 1547 void WebIntentPickerViews::ResetContents() {
1342 // Abandon both web contents and webview. 1548 // Abandon both web contents and webview.
1343 webview_->SetWebContents(NULL); 1549 webview_->SetWebContents(NULL);
1344 inline_web_contents_.reset(); 1550 inline_web_contents_.reset();
1345 webview_ = NULL; 1551 webview_ = NULL;
1346 1552
1347 // Re-initialize the UI. 1553 // Re-initialize the UI.
1348 UpdateContents(); 1554 UpdateContents();
1349 1555
1350 // Restore previous state. 1556 // Restore previous state.
1351 extensions_->Update(); 1557 if (extensions_)
1352 action_label_->SetText(action_text_); 1558 extensions_->Update();
1559 if (action_label_)
1560 action_label_->SetText(action_text_);
1353 contents_->Layout(); 1561 contents_->Layout();
1354 SizeToContents(); 1562 SizeToContents();
1355 } 1563 }
1356 1564
1357 void WebIntentPickerViews::SizeToContents() { 1565 void WebIntentPickerViews::SizeToContents() {
1358 gfx::Size client_size = contents_->GetPreferredSize(); 1566 gfx::Size client_size = contents_->GetPreferredSize();
1359 gfx::Rect client_bounds(client_size); 1567 gfx::Rect client_bounds(client_size);
1360 gfx::Rect new_window_bounds = window_->non_client_view()->frame_view()-> 1568 gfx::Rect new_window_bounds = window_->non_client_view()->frame_view()->
1361 GetWindowBoundsForClientBounds(client_bounds); 1569 GetWindowBoundsForClientBounds(client_bounds);
1362 window_->CenterWindow(new_window_bounds.size()); 1570 window_->CenterWindow(new_window_bounds.size());
1363 } 1571 }
1364 1572
1365 void WebIntentPickerViews::ClearContents() { 1573 void WebIntentPickerViews::ClearContents() {
1366 DCHECK(contents_); 1574 DCHECK(contents_);
1367 // The call RemoveAllChildViews(true) deletes all children of |contents|. If 1575 // The call RemoveAllChildViews(true) deletes all children of |contents|. If
1368 // we do not set our weak pointers to NULL, then they will continue to point 1576 // we do not set our weak pointers to NULL, then they will continue to point
1369 // to where the deleted objects used to be, i.e. unitialized memory. This 1577 // to where the deleted objects used to be, i.e. unitialized memory. This
1370 // would cause hard-to-explain crashes. 1578 // would cause hard-to-explain crashes.
1371 contents_->RemoveAllChildViews(true); 1579 contents_->RemoveAllChildViews(true);
1372 action_label_ = NULL; 1580 action_label_ = NULL;
1373 suggestions_label_ = NULL;
1374 extensions_ = NULL; 1581 extensions_ = NULL;
1375 more_suggestions_link_ = NULL; 1582 more_suggestions_link_ = NULL;
1583 inline_service_icon_ = NULL;
1376 choose_another_service_link_ = NULL; 1584 choose_another_service_link_ = NULL;
1377 } 1585 }
1586
1587 void WebIntentPickerViews::RefreshInlineServiceIcon() {
1588 DCHECK(inline_service_icon_);
1589 const WebIntentPickerModel::InstalledService* inline_service =
1590 model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
1591 if (inline_service)
1592 inline_service_icon_->SetImage(inline_service->favicon.ToImageSkia());
1593 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698