| Index: chrome/browser/ui/views/web_intent_picker_views.cc
|
| diff --git a/chrome/browser/ui/views/web_intent_picker_views.cc b/chrome/browser/ui/views/web_intent_picker_views.cc
|
| index e208843e534528ff80e07ee9346aae27da8bb6be..9341aad2467dd46ce712c50094355eb861c4a119 100644
|
| --- a/chrome/browser/ui/views/web_intent_picker_views.cc
|
| +++ b/chrome/browser/ui/views/web_intent_picker_views.cc
|
| @@ -7,10 +7,13 @@
|
|
|
| #include "base/memory/scoped_vector.h"
|
| #include "base/time.h"
|
| +#include "base/timer.h"
|
| #include "base/utf_string_conversions.h"
|
| +#include "chrome/browser/download/download_util.h"
|
| #include "chrome/browser/tab_contents/tab_util.h"
|
| #include "chrome/browser/ui/browser_finder.h"
|
| #include "chrome/browser/ui/browser_navigator.h"
|
| +#include "chrome/browser/ui/constrained_window_constants.h"
|
| #include "chrome/browser/ui/intents/web_intent_inline_disposition_delegate.h"
|
| #include "chrome/browser/ui/intents/web_intent_picker.h"
|
| #include "chrome/browser/ui/intents/web_intent_picker_delegate.h"
|
| @@ -46,6 +49,7 @@
|
| #include "ui/views/controls/label.h"
|
| #include "ui/views/controls/link.h"
|
| #include "ui/views/controls/link_listener.h"
|
| +#include "ui/views/controls/separator.h"
|
| #include "ui/views/controls/throbber.h"
|
| #include "ui/views/controls/webview/webview.h"
|
| #include "ui/views/layout/box_layout.h"
|
| @@ -65,6 +69,12 @@ namespace {
|
| // The color used to dim disabled elements.
|
| const SkColor kHalfOpacityWhite = SkColorSetARGB(128, 255, 255, 255);
|
|
|
| +// The color used to display an enabled label.
|
| +const SkColor kEnabledLabelColor = SkColorSetRGB(51, 51, 51);
|
| +
|
| +// The color used to display an enabled link.
|
| +const SkColor kEnabledLinkColor = SkColorSetRGB(17, 85, 204);
|
| +
|
| // The color used to display a disabled link.
|
| const SkColor kDisabledLinkColor = SkColorSetRGB(128, 128, 128);
|
|
|
| @@ -80,6 +90,9 @@ const int kMinRowCount = 4;
|
| // Maximum number of action buttons - do not add suggestions to reach.
|
| const int kMaxRowCount = 8;
|
|
|
| +// The vertical padding around the UI elements in the waiting view.
|
| +const int kWaitingViewVerticalPadding = 40;
|
| +
|
| // Enables or disables all child views of |view|.
|
| void EnableChildViews(views::View* view, bool enabled) {
|
| for (int i = 0; i < view->child_count(); ++i) {
|
| @@ -100,7 +113,80 @@ views::ImageButton* CreateCloseButton(views::ButtonListener* listener) {
|
| rb.GetImageSkiaNamed(IDR_SHARED_IMAGES_X_HOVER));
|
| return close_button;
|
| }
|
| -// SarsView -------------------------------------------------------------------
|
| +
|
| +// Creates a label.
|
| +views::Label* CreateLabel() {
|
| + views::Label* label = new views::Label();
|
| + label->SetEnabledColor(kEnabledLabelColor);
|
| + label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + return label;
|
| +}
|
| +
|
| +// Creates a title-style label.
|
| +views::Label* CreateTitleLabel() {
|
| + views::Label* label = CreateLabel();
|
| + label->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
|
| + ui::ResourceBundle::MediumFont));
|
| + const int kLabelBuiltinTopPadding = 5;
|
| + label->set_border(views::Border::CreateEmptyBorder(
|
| + WebIntentPicker::kContentAreaBorder -
|
| + ConstrainedWindowConstants::kCloseButtonPadding -
|
| + kLabelBuiltinTopPadding,
|
| + 0, 0, 0));
|
| + return label;
|
| +}
|
| +
|
| +// Creates a link.
|
| +views::Link* CreateLink() {
|
| + views::Link* link = new views::Link();
|
| + link->SetEnabledColor(kEnabledLinkColor);
|
| + link->SetDisabledColor(kDisabledLinkColor);
|
| + link->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + return link;
|
| +}
|
| +
|
| +// Creates a header for the inline disposition dialog.
|
| +views::View* CreateInlineDispositionHeader(
|
| + views::ImageView* app_icon,
|
| + views::Label* app_title,
|
| + views::Link* use_another_service_link) {
|
| + views::View* header = new views::View();
|
| + views::GridLayout* grid_layout = new views::GridLayout(header);
|
| + const int kIconBuiltinTopPadding = 6;
|
| + grid_layout->SetInsets(
|
| + WebIntentPicker::kContentAreaBorder -
|
| + ConstrainedWindowConstants::kCloseButtonPadding -
|
| + kIconBuiltinTopPadding,
|
| + 0, 0, 0);
|
| + header->SetLayoutManager(grid_layout);
|
| + views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
|
| + header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
|
| + GridLayout::USE_PREF, 0, 0); // App icon.
|
| + header_cs->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
|
| + header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // App title.
|
| + header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
|
| + header_cs->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Use another app link.
|
| + grid_layout->StartRow(0, 0);
|
| + grid_layout->AddView(app_icon);
|
| + grid_layout->AddView(app_title);
|
| + grid_layout->AddView(use_another_service_link);
|
| + header->Layout();
|
| + return header;
|
| +}
|
| +
|
| +// Checks whether the inline disposition dialog should show the link for using
|
| +// another service.
|
| +bool IsUseAnotherServiceVisible(WebIntentPickerModel* model) {
|
| + DCHECK(model);
|
| + return model->show_use_another_service() &&
|
| + (model->GetInstalledServiceCount() > 1 ||
|
| + model->GetSuggestedExtensionCount());
|
| +}
|
| +
|
| +
|
| +// StarsView -------------------------------------------------------------------
|
|
|
| // A view that displays 5 stars: empty, full or half full, given a rating in
|
| // the range [0,5].
|
| @@ -141,6 +227,7 @@ StarsView::StarsView(double rating)
|
| StarsView::~StarsView() {
|
| }
|
|
|
| +
|
| // ThrobberNativeTextButton ----------------------------------------------------
|
|
|
| // A native text button that can display a throbber in place of its icon. Much
|
| @@ -268,142 +355,169 @@ void ThrobberNativeTextButton::Run() {
|
| SchedulePaint();
|
| }
|
|
|
| -// WaitingView ----------------------------------------------------------
|
| -class WaitingView : public views::View {
|
| +
|
| +// SpinnerProgressIndicator ----------------------------------------------------
|
| +class SpinnerProgressIndicator : public views::View {
|
| public:
|
| - WaitingView(views::ButtonListener* listener, bool use_close_button);
|
| + SpinnerProgressIndicator();
|
| + virtual ~SpinnerProgressIndicator();
|
| +
|
| + void SetPercentDone(int percent);
|
| + void SetIndeterminate(bool indetereminate);
|
| +
|
| + // Overridden from views::View.
|
| + virtual void Paint(gfx::Canvas* canvas) OVERRIDE;
|
| + virtual gfx::Size GetPreferredSize() OVERRIDE;
|
|
|
| private:
|
| - DISALLOW_COPY_AND_ASSIGN(WaitingView);
|
| + void UpdateTimer();
|
| + int GetProgressAngle();
|
| +
|
| + static const int kTimerIntervalMs = 1000 / 30;
|
| + static const int kSpinRateDegreesPerSecond = 270;
|
| +
|
| + int percent_done_;
|
| + int indeterminate_;
|
| +
|
| + base::TimeTicks start_time_;
|
| + base::RepeatingTimer<SpinnerProgressIndicator> timer_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(SpinnerProgressIndicator);
|
| };
|
|
|
| -WaitingView::WaitingView(views::ButtonListener* listener,
|
| - bool use_close_button) {
|
| - views::GridLayout* layout = new views::GridLayout(this);
|
| - layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| - layout->SetInsets(WebIntentPicker::kContentAreaBorder,
|
| - WebIntentPicker::kContentAreaBorder,
|
| - WebIntentPicker::kContentAreaBorder,
|
| - WebIntentPicker::kContentAreaBorder);
|
| - SetLayoutManager(layout);
|
| +SpinnerProgressIndicator::SpinnerProgressIndicator()
|
| + : percent_done_(0),
|
| + indeterminate_(true) {}
|
|
|
| - views::ColumnSet* cs = layout->AddColumnSet(0);
|
| - views::ColumnSet* header_cs = NULL;
|
| - if (use_close_button) {
|
| - header_cs = layout->AddColumnSet(1);
|
| - header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close Button.
|
| - }
|
| - cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| - cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER,
|
| - 1, GridLayout::USE_PREF, 0, 0);
|
| - cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| +SpinnerProgressIndicator::~SpinnerProgressIndicator() {
|
| +}
|
|
|
| - // Create throbber.
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| - const gfx::ImageSkia* frames =
|
| - rb.GetImageNamed(IDR_SPEECH_INPUT_SPINNER).ToImageSkia();
|
| - views::Throbber* throbber = new views::Throbber(kThrobberFrameTimeMs, true);
|
| - throbber->SetFrames(frames);
|
| - throbber->Start();
|
| +void SpinnerProgressIndicator::SetPercentDone(int percent) {
|
| + percent_done_ = percent;
|
| + SchedulePaint();
|
| + UpdateTimer();
|
| +}
|
|
|
| - // Create text.
|
| - views::Label* label = new views::Label();
|
| - label->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
|
| - label->SetFont(rb.GetFont(ui::ResourceBundle::MediumBoldFont));
|
| - label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
|
| +void SpinnerProgressIndicator::SetIndeterminate(bool indetereminate) {
|
| + indeterminate_ = indetereminate;
|
| + SchedulePaint();
|
| + UpdateTimer();
|
| +}
|
|
|
| - // Layout the view.
|
| - if (use_close_button) {
|
| - layout->StartRow(0, 1);
|
| - layout->AddView(CreateCloseButton(listener));
|
| +void SpinnerProgressIndicator::Paint(gfx::Canvas* canvas) {
|
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| + gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
|
| + gfx::ImageSkia* bg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_BACKGROUND);
|
| + download_util::PaintCustomDownloadProgress(
|
| + canvas,
|
| + *bg,
|
| + *fg,
|
| + fg->width(),
|
| + bounds(),
|
| + GetProgressAngle(),
|
| + indeterminate_ ? -1 : percent_done_);
|
| +}
|
| +
|
| +gfx::Size SpinnerProgressIndicator::GetPreferredSize() {
|
| + ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| + gfx::ImageSkia* fg = rb.GetImageSkiaNamed(IDR_WEB_INTENT_PROGRESS_FOREGROUND);
|
| + return fg->size();
|
| +}
|
| +
|
| +void SpinnerProgressIndicator::UpdateTimer() {
|
| + if (!parent() || !indeterminate_) {
|
| + timer_.Stop();
|
| + return;
|
| }
|
|
|
| - layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
|
| - layout->StartRow(0, 0);
|
| - layout->AddView(throbber);
|
| - layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
|
| - layout->StartRow(0, 0);
|
| - layout->AddView(label);
|
| - layout->AddPaddingRow(0, views::kUnrelatedControlLargeVerticalSpacing);
|
| + if (!timer_.IsRunning()) {
|
| + start_time_ = base::TimeTicks::Now();
|
| + timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(kTimerIntervalMs),
|
| + this, &SpinnerProgressIndicator::SchedulePaint);
|
| + }
|
| }
|
|
|
| -// SuggestedExtensionsLayout ---------------------------------------------------
|
| +int SpinnerProgressIndicator::GetProgressAngle() {
|
| + if (!indeterminate_)
|
| + return download_util::kStartAngleDegrees;
|
| + base::TimeDelta delta = base::TimeTicks::Now() - start_time_;
|
| + int angle = delta.InSecondsF() * kSpinRateDegreesPerSecond;
|
| + return angle % 360;
|
| +}
|
|
|
| -// TODO(groby): Extremely fragile code, relies on order and number of fields.
|
| -// Would probably be better off as GridLayout or similar. Also see review
|
| -// comments on http://codereview.chromium.org/10909183
|
|
|
| -// A LayoutManager used by a row of the IntentsView. It is similar
|
| -// to a BoxLayout, but it right aligns the rightmost view (which is the install
|
| -// button). It also uses the maximum height of all views in the row as a
|
| -// preferred height so it doesn't change when the install button is hidden.
|
| -class SuggestedExtensionsLayout : public views::LayoutManager {
|
| +// WaitingView ----------------------------------------------------------
|
| +class WaitingView : public views::View {
|
| public:
|
| - SuggestedExtensionsLayout();
|
| - virtual ~SuggestedExtensionsLayout();
|
| -
|
| - // Implementation of views::LayoutManager.
|
| - virtual void Layout(views::View* host) OVERRIDE;
|
| - virtual gfx::Size GetPreferredSize(views::View* host) OVERRIDE;
|
| + WaitingView(views::ButtonListener* listener, bool use_close_button);
|
| + virtual ~WaitingView();
|
|
|
| private:
|
| - DISALLOW_COPY_AND_ASSIGN(SuggestedExtensionsLayout);
|
| + DISALLOW_COPY_AND_ASSIGN(WaitingView);
|
| };
|
|
|
| -SuggestedExtensionsLayout::SuggestedExtensionsLayout() {
|
| -}
|
| -
|
| -SuggestedExtensionsLayout::~SuggestedExtensionsLayout() {
|
| -}
|
| -
|
| -void SuggestedExtensionsLayout::Layout(views::View* host) {
|
| - gfx::Rect child_area(host->GetLocalBounds());
|
| - child_area.Inset(host->GetInsets());
|
| - int x = child_area.x();
|
| - int y = child_area.y();
|
| -
|
| - for (int i = 0; i < host->child_count(); ++i) {
|
| - views::View* child = host->child_at(i);
|
| - if (!child->visible())
|
| - continue;
|
| - gfx::Size size(child->GetPreferredSize());
|
| - gfx::Rect child_bounds(x, y, size.width(), child_area.height());
|
| - if (i == host->child_count() - 1) {
|
| - // Last child (the install button) should be right aligned.
|
| - child_bounds.set_x(std::max(child_area.width() - size.width(), x));
|
| - } else if (i == 1) {
|
| - // Label is considered fixed width, to align ratings widget.
|
| - DCHECK_LE(size.width(), WebIntentPicker::kTitleLinkMaxWidth);
|
| - x += WebIntentPicker::kTitleLinkMaxWidth +
|
| - views::kRelatedControlHorizontalSpacing;
|
| - } else {
|
| - x += size.width() + views::kRelatedControlHorizontalSpacing;
|
| - }
|
| - // Clamp child view bounds to |child_area|.
|
| - child->SetBoundsRect(child_bounds.Intersect(child_area));
|
| - }
|
| +WaitingView::WaitingView(views::ButtonListener* listener,
|
| + bool use_close_button) {
|
| + views::GridLayout* layout = new views::GridLayout(this);
|
| + layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| + const int kMessageBuiltinBottomPadding = 3;
|
| + layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding,
|
| + 0,
|
| + kWaitingViewVerticalPadding - kMessageBuiltinBottomPadding,
|
| + 0);
|
| + SetLayoutManager(layout);
|
| +
|
| + enum GridLayoutColumnSets {
|
| + HEADER_ROW,
|
| + CONTENT_ROW,
|
| + };
|
| + views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW);
|
| + header_cs->AddPaddingColumn(1, 1);
|
| + header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| + GridLayout::USE_PREF, 0, 0);
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kCloseButtonPadding);
|
| +
|
| + views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW);
|
| + content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| + content_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0);
|
| + content_cs->AddPaddingColumn(0, views::kPanelHorizIndentation);
|
| +
|
| + // Close button
|
| + layout->StartRow(0, HEADER_ROW);
|
| + views::ImageButton* close_button = CreateCloseButton(listener);
|
| + layout->AddView(close_button);
|
| + close_button->SetVisible(use_close_button);
|
| +
|
| + // Throbber
|
| + layout->AddPaddingRow(0,
|
| + kWaitingViewVerticalPadding -
|
| + ConstrainedWindowConstants::kCloseButtonPadding -
|
| + close_button->GetPreferredSize().height());
|
| + layout->StartRow(0, CONTENT_ROW);
|
| + SpinnerProgressIndicator* throbber = new SpinnerProgressIndicator();
|
| + layout->AddView(throbber);
|
| +
|
| + // Message
|
| + const int kMessageBuiltinTopPadding = 5;
|
| + layout->AddPaddingRow(0,
|
| + ConstrainedWindowConstants::kRowPadding -
|
| + kMessageBuiltinTopPadding);
|
| + layout->StartRow(0, CONTENT_ROW);
|
| + views::Label* label = CreateLabel();
|
| + label->SetHorizontalAlignment(views::Label::ALIGN_CENTER);
|
| + label->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_WAIT_FOR_CWS));
|
| + layout->AddView(label);
|
| +
|
| + // Start the throbber.
|
| + throbber->SetIndeterminate(true);
|
| }
|
|
|
| -gfx::Size SuggestedExtensionsLayout::GetPreferredSize(views::View* host) {
|
| - int width = 0;
|
| - int height = 0;
|
| - for (int i = 0; i < host->child_count(); ++i) {
|
| - views::View* child = host->child_at(i);
|
| - gfx::Size size(child->GetPreferredSize());
|
| - // The preferred height includes visible and invisible children. This
|
| - // prevents jank when a child is hidden.
|
| - height = std::max(height, size.height());
|
| - if (!child->visible())
|
| - continue;
|
| - if (i != 0)
|
| - width += views::kRelatedControlHorizontalSpacing;
|
| - }
|
| - gfx::Insets insets(host->GetInsets());
|
| - return gfx::Size(width + insets.width(), height + insets.height());
|
| +WaitingView::~WaitingView() {
|
| }
|
|
|
| +
|
| // IntentRowView --------------------------------------------------
|
|
|
| // A view for each row in the IntentsView. It displays information
|
| @@ -545,12 +659,14 @@ IntentRowView* IntentRowView::CreateHandlerRow(
|
| if (service != NULL) {
|
| view = new IntentRowView(ACTION_INVOKE, tag);
|
| icon = service->favicon.ToImageSkia();
|
| - label = new views::Label(elided_title);
|
| + label = CreateLabel();
|
| + label->SetText(elided_title);
|
| } else {
|
| view = new IntentRowView(ACTION_INSTALL, tag);
|
| view->extension_id_ = extension->id;
|
| icon = extension->icon.ToImageSkia();
|
| - views::Link* link = new views::Link(elided_title);
|
| + views::Link* link = CreateLink();
|
| + link->SetText(elided_title);
|
| link->set_listener(view);
|
| label = link;
|
| stars = new StarsView(extension->average_rating);
|
| @@ -558,25 +674,43 @@ IntentRowView* IntentRowView::CreateHandlerRow(
|
|
|
| view->delegate_ = delegate;
|
|
|
| - view->SetLayoutManager(new SuggestedExtensionsLayout);
|
| + views::GridLayout* grid_layout = new views::GridLayout(view);
|
| + view->SetLayoutManager(grid_layout);
|
| +
|
| + views::ColumnSet* columns = grid_layout->AddColumnSet(0);
|
| + columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Icon.
|
| + columns->AddPaddingColumn(0, WebIntentPicker::kIconTextPadding);
|
| + columns->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| + GridLayout::FIXED, WebIntentPicker::kTitleLinkMaxWidth, 0);
|
| + const int kStarRatingHorizontalSpacing = 20;
|
| + columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
|
| + if (stars != NULL) {
|
| + columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Star rating.
|
| + columns->AddPaddingColumn(0, kStarRatingHorizontalSpacing);
|
| + }
|
| + columns->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
|
| + GridLayout::FIXED, preferred_width, 0); // Button.
|
|
|
| - view->icon_ = new views::ImageView();
|
| + grid_layout->StartRow(0, 0);
|
|
|
| + view->icon_ = new views::ImageView();
|
| view->icon_->SetImage(icon);
|
| - view->AddChildView(view->icon_);
|
| + grid_layout->AddView(view->icon_);
|
|
|
| view->title_link_ = label;
|
| - view->AddChildView(view->title_link_);
|
| + grid_layout->AddView(view->title_link_);
|
|
|
| if (stars != NULL) {
|
| view->stars_ = stars;
|
| - view->AddChildView(view->stars_);
|
| + grid_layout->AddView(view->stars_);
|
| }
|
|
|
| view->install_button_ = new ThrobberNativeTextButton(
|
| view, view->GetActionButtonMessage());
|
| view->install_button_->set_preferred_width(preferred_width);
|
| - view->AddChildView(view->install_button_);
|
| + grid_layout->AddView(view->install_button_);
|
|
|
| return view;
|
| }
|
| @@ -641,6 +775,7 @@ string16 IntentRowView::GetActionButtonMessage() {
|
| return l10n_util::GetStringUTF16(message_id);
|
| }
|
|
|
| +
|
| // IntentsView -----------------------------------------------------
|
|
|
| // A view that contains both installed services and suggested extensions
|
| @@ -702,8 +837,9 @@ void IntentsView::Update() {
|
| button_width_ = std::max(
|
| kButtonWidth, size_helper.GetPreferredSize().width());
|
|
|
| - views::BoxLayout* layout = new views::BoxLayout(
|
| - views::BoxLayout::kVertical, 0, 0, views::kRelatedControlVerticalSpacing);
|
| + const int kAppRowVerticalSpacing = 10;
|
| + views::BoxLayout* layout = new views::BoxLayout(views::BoxLayout::kVertical,
|
| + 0, 0, kAppRowVerticalSpacing);
|
| SetLayoutManager(layout);
|
|
|
| int available_rows = kMaxRowCount;
|
| @@ -755,11 +891,12 @@ void IntentsView::OnEnabledChanged() {
|
|
|
| } // namespace
|
|
|
| +
|
| // WebIntentPickerViews --------------------------------------------------------
|
|
|
| // Views implementation of WebIntentPicker.
|
| class WebIntentPickerViews : public views::ButtonListener,
|
| - public views::DialogDelegate,
|
| + public views::WidgetDelegate,
|
| public views::LinkListener,
|
| public WebIntentPicker,
|
| public WebIntentPickerModelObserver,
|
| @@ -775,14 +912,12 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| virtual void ButtonPressed(views::Button* sender,
|
| const ui::Event& event) OVERRIDE;
|
|
|
| - // views::DialogDelegate implementation.
|
| + // views::WidgetDelegate implementation.
|
| virtual void WindowClosing() OVERRIDE;
|
| virtual void DeleteDelegate() OVERRIDE;
|
| virtual views::Widget* GetWidget() OVERRIDE;
|
| virtual const views::Widget* GetWidget() const OVERRIDE;
|
| virtual views::View* GetContentsView() OVERRIDE;
|
| - virtual int GetDialogButtons() const OVERRIDE;
|
| - virtual bool Cancel() OVERRIDE;
|
|
|
| // LinkListener implementation.
|
| virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
|
| @@ -817,9 +952,21 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| size_t tag) OVERRIDE;
|
|
|
| private:
|
| + enum WebIntentPickerViewsState {
|
| + INITIAL,
|
| + WAITING,
|
| + NO_SERVICES,
|
| + LIST_SERVICES,
|
| + INLINE_SERVICE,
|
| + } state_;
|
| +
|
| // Update picker contents to reflect the current state of the model.
|
| void UpdateContents();
|
|
|
| + // Shows a spinner and notifies the user that we are waiting for information
|
| + // from the Chrome Web Store.
|
| + void ShowWaitingForSuggestions();
|
| +
|
| // Updates the dialog with the list of available services, suggestions,
|
| // and a nice link to CWS to find more suggestions. This is the "Main"
|
| // view of the picker.
|
| @@ -842,6 +989,13 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| // of the picker.
|
| const string16 GetActionTitle();
|
|
|
| + // Refresh the icon for the inline disposition service that is being
|
| + // displayed.
|
| + void RefreshInlineServiceIcon();
|
| +
|
| + // Refresh the extensions control in the picker.
|
| + void RefreshExtensions();
|
| +
|
| // A weak pointer to the WebIntentPickerDelegate to notify when the user
|
| // chooses a service or cancels.
|
| WebIntentPickerDelegate* delegate_;
|
| @@ -853,10 +1007,6 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| // Created locally, owned by Views.
|
| views::Label* action_label_;
|
|
|
| - // A weak pointer to the header label for the extension suggestions.
|
| - // Created locally, owned by Views.
|
| - views::Label* suggestions_label_;
|
| -
|
| // A weak pointer to the intents view.
|
| // Created locally, owned by Views view hierarchy.
|
| IntentsView* extensions_;
|
| @@ -883,6 +1033,9 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| // Created locally, owned by Views.
|
| views::Link* more_suggestions_link_;
|
|
|
| + // The icon for the inline disposition service.
|
| + views::ImageView* inline_service_icon_;
|
| +
|
| // A weak pointer to the choose another service link.
|
| // Created locally, owned by Views.
|
| views::Link* choose_another_service_link_;
|
| @@ -890,10 +1043,6 @@ class WebIntentPickerViews : public views::ButtonListener,
|
| // Weak pointer to "Waiting for CWS" display. Owned by parent view.
|
| WaitingView* waiting_view_;
|
|
|
| - // Set to true when displaying the inline disposition web contents. Used to
|
| - // prevent laying out the inline disposition widgets twice.
|
| - bool displaying_web_contents_;
|
| -
|
| // The text for the current action.
|
| string16 action_text_;
|
|
|
| @@ -922,29 +1071,31 @@ WebIntentPicker* WebIntentPicker::Create(content::WebContents* web_contents,
|
| WebIntentPickerViews::WebIntentPickerViews(TabContents* tab_contents,
|
| WebIntentPickerDelegate* delegate,
|
| WebIntentPickerModel* model)
|
| - : delegate_(delegate),
|
| + : state_(INITIAL),
|
| + delegate_(delegate),
|
| model_(model),
|
| action_label_(NULL),
|
| - suggestions_label_(NULL),
|
| extensions_(NULL),
|
| tab_contents_(tab_contents),
|
| webview_(new views::WebView(tab_contents->profile())),
|
| window_(NULL),
|
| more_suggestions_link_(NULL),
|
| + inline_service_icon_(NULL),
|
| choose_another_service_link_(NULL),
|
| waiting_view_(NULL),
|
| - displaying_web_contents_(false),
|
| can_close_(true) {
|
| bool enable_chrome_style = chrome::IsFramelessConstrainedDialogEnabled();
|
| use_close_button_ = enable_chrome_style;
|
|
|
| model_->set_observer(this);
|
| contents_ = new views::View();
|
| - // Show the dialog.
|
| - window_ = new ConstrainedWindowViews(tab_contents->web_contents(),
|
| - this,
|
| - enable_chrome_style);
|
| + contents_->set_background(views::Background::CreateSolidBackground(
|
| + ConstrainedWindow::GetBackgroundColor()));
|
|
|
| + // Show the dialog.
|
| + window_ = new ConstrainedWindowViews(tab_contents->web_contents(), this,
|
| + enable_chrome_style,
|
| + ConstrainedWindowViews::NO_INSETS);
|
| if (model_->IsInlineDisposition())
|
| OnInlineDisposition(string16(), model_->inline_disposition_url());
|
| else
|
| @@ -980,14 +1131,6 @@ views::View* WebIntentPickerViews::GetContentsView() {
|
| return contents_;
|
| }
|
|
|
| -int WebIntentPickerViews::GetDialogButtons() const {
|
| - return ui::DIALOG_BUTTON_NONE;
|
| -}
|
| -
|
| -bool WebIntentPickerViews::Cancel() {
|
| - return can_close_;
|
| -}
|
| -
|
| void WebIntentPickerViews::LinkClicked(views::Link* source, int event_flags) {
|
| if (source == more_suggestions_link_) {
|
| delegate_->OnSuggestionsLinkClicked(
|
| @@ -1007,11 +1150,11 @@ void WebIntentPickerViews::Close() {
|
|
|
| void WebIntentPickerViews::SetActionString(const string16& action) {
|
| action_text_ = action;
|
| -
|
| - if (action_label_)
|
| + if (action_label_) {
|
| action_label_->SetText(GetActionTitle());
|
| contents_->Layout();
|
| SizeToContents();
|
| + }
|
| }
|
|
|
| void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) {
|
| @@ -1020,6 +1163,7 @@ void WebIntentPickerViews::OnExtensionInstallSuccess(const std::string& id) {
|
|
|
| void WebIntentPickerViews::OnExtensionInstallFailure(const std::string& id) {
|
| extensions_->StopThrobber();
|
| + extensions_->SetEnabled(true);
|
| more_suggestions_link_->SetEnabled(true);
|
| can_close_ = true;
|
| contents_->Layout();
|
| @@ -1040,139 +1184,185 @@ void WebIntentPickerViews::OnPendingAsyncCompleted() {
|
| }
|
|
|
| void WebIntentPickerViews::ShowNoServicesMessage() {
|
| - ClearContents();
|
| -
|
| - views::GridLayout* grid_layout = new views::GridLayout(contents_);
|
| - contents_->SetLayoutManager(grid_layout);
|
| -
|
| - grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
|
| - kContentAreaBorder, kContentAreaBorder);
|
| - views::ColumnSet* main_cs = grid_layout->AddColumnSet(0);
|
| - main_cs->AddColumn(GridLayout::FILL, GridLayout::LEADING, 1,
|
| - GridLayout::USE_PREF, 0, 0);
|
| -
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| + if (state_ == NO_SERVICES)
|
| + return;
|
| + state_ = NO_SERVICES;
|
|
|
| - grid_layout->StartRow(0, 0);
|
| - views::Label* header = new views::Label();
|
| - header->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| - header->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
|
| - header->SetText(l10n_util::GetStringUTF16(
|
| + ClearContents();
|
| + views::GridLayout* layout = new views::GridLayout(contents_);
|
| + layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| + const int kContentBuiltinBottomPadding = 3;
|
| + layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding,
|
| + 0,
|
| + ConstrainedWindowConstants::kClientBottomPadding -
|
| + kContentBuiltinBottomPadding,
|
| + 0);
|
| + contents_->SetLayoutManager(layout);
|
| +
|
| + enum GridLayoutColumnSets {
|
| + HEADER_ROW,
|
| + CONTENT_ROW,
|
| + };
|
| + views::ColumnSet* header_cs = layout->AddColumnSet(HEADER_ROW);
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| + header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Title
|
| + header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Close button
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kCloseButtonPadding);
|
| +
|
| + views::ColumnSet* content_cs = layout->AddColumnSet(CONTENT_ROW);
|
| + content_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| + content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Body
|
| + content_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| +
|
| + // Header
|
| + layout->StartRow(0, HEADER_ROW);
|
| + views::Label* title = CreateTitleLabel();
|
| + title->SetText(l10n_util::GetStringUTF16(
|
| IDS_INTENT_PICKER_NO_SERVICES_TITLE));
|
| - grid_layout->AddView(header);
|
| -
|
| - grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
|
| -
|
| - grid_layout->StartRow(0, 0);
|
| - views::Label* body = new views::Label();
|
| + layout->AddView(title);
|
| +
|
| + views::ImageButton* close_button = CreateCloseButton(this);
|
| + layout->AddView(close_button);
|
| + close_button->SetVisible(use_close_button_);
|
| +
|
| + // Content
|
| + const int kHeaderBuiltinBottomPadding = 4;
|
| + const int kContentBuiltinTopPadding = 5;
|
| + layout->AddPaddingRow(0,
|
| + ConstrainedWindowConstants::kRowPadding -
|
| + kHeaderBuiltinBottomPadding -
|
| + kContentBuiltinTopPadding);
|
| + layout->StartRow(0, CONTENT_ROW);
|
| + views::Label* body = CreateLabel();
|
| body->SetMultiLine(true);
|
| - body->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| body->SetText(l10n_util::GetStringUTF16(IDS_INTENT_PICKER_NO_SERVICES));
|
| - grid_layout->AddView(body);
|
| + layout->AddView(body);
|
|
|
| - int height = contents_->GetHeightForWidth(kWindowMinWidth);
|
| - contents_->SetSize(gfx::Size(kWindowMinWidth, height));
|
| + int height = contents_->GetHeightForWidth(WebIntentPicker::kWindowMinWidth);
|
| + contents_->SetSize(gfx::Size(WebIntentPicker::kWindowMinWidth, height));
|
| + contents_->Layout();
|
| }
|
|
|
| void WebIntentPickerViews::OnInlineDispositionWebContentsLoaded(
|
| content::WebContents* web_contents) {
|
| - if (displaying_web_contents_)
|
| + if (state_ == INLINE_SERVICE)
|
| return;
|
| + state_ = INLINE_SERVICE;
|
|
|
| // Replace the picker with the inline disposition.
|
| ClearContents();
|
| -
|
| views::GridLayout* grid_layout = new views::GridLayout(contents_);
|
| + grid_layout->set_minimum_size(gfx::Size(WebIntentPicker::kWindowMinWidth, 0));
|
| + grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding, 0,
|
| + ConstrainedWindowConstants::kClientBottomPadding, 0);
|
| contents_->SetLayoutManager(grid_layout);
|
|
|
| - grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
|
| - kContentAreaBorder, kContentAreaBorder);
|
| - views::ColumnSet* header_cs = grid_layout->AddColumnSet(0);
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Icon.
|
| - header_cs->AddPaddingColumn(0, 4);
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Title.
|
| - header_cs->AddPaddingColumn(0, 4);
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Link.
|
| - header_cs->AddPaddingColumn(1, views::kUnrelatedControlHorizontalSpacing);
|
| - if (use_close_button_) {
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close Button.
|
| - }
|
| -
|
| - views::ColumnSet* full_cs = grid_layout->AddColumnSet(1);
|
| - full_cs->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
|
| - GridLayout::USE_PREF, 0, 0);
|
| + enum GridLayoutColumnSets {
|
| + HEADER_ROW,
|
| + SEPARATOR_ROW,
|
| + WEB_CONTENTS_ROW,
|
| + };
|
| + views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW);
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| + header_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Icon, title, link.
|
| + header_cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
|
| + header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Close button.
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kCloseButtonPadding);
|
| +
|
| + views::ColumnSet* sep_cs = grid_layout->AddColumnSet(SEPARATOR_ROW);
|
| + sep_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Separator.
|
| +
|
| + views::ColumnSet* contents_cs = grid_layout->AddColumnSet(WEB_CONTENTS_ROW);
|
| + contents_cs->AddPaddingColumn(0, 1);
|
| + contents_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Web contents.
|
| + contents_cs->AddPaddingColumn(0, 1);
|
| +
|
| + // Header.
|
| + grid_layout->StartRow(0, HEADER_ROW);
|
|
|
| const WebIntentPickerModel::InstalledService* service =
|
| model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
|
|
|
| - // Header row.
|
| - grid_layout->StartRow(0, 0);
|
| - views::ImageView* icon = new views::ImageView();
|
| - icon->SetImage(service->favicon.ToImageSkia());
|
| - grid_layout->AddView(icon);
|
| -
|
| - string16 elided_title = ui::ElideText(
|
| - service->title, gfx::Font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END);
|
| - views::Label* title = new views::Label(elided_title);
|
| - grid_layout->AddView(title);
|
| - // Add link for "choose another service" if other suggestions are available
|
| - // or if more than one (the current) service is installed.
|
| - if (model_->show_use_another_service() &&
|
| - (model_->GetInstalledServiceCount() > 1 ||
|
| - model_->GetSuggestedExtensionCount())) {
|
| - choose_another_service_link_ = new views::Link(
|
| - l10n_util::GetStringUTF16(IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
|
| - grid_layout->AddView(choose_another_service_link_);
|
| - choose_another_service_link_->set_listener(this);
|
| - }
|
| -
|
| - if (use_close_button_)
|
| - grid_layout->AddView(CreateCloseButton(this));
|
| + if (!inline_service_icon_)
|
| + inline_service_icon_ = new views::ImageView();
|
| + inline_service_icon_->SetImage(service->favicon.ToImageSkia());
|
| +
|
| + views::Label* title = CreateLabel();
|
| + title->SetText(ui::ElideText(
|
| + service->title, title->font(), kTitleLinkMaxWidth, ui::ELIDE_AT_END));
|
| +
|
| + if (!choose_another_service_link_)
|
| + choose_another_service_link_ = CreateLink();
|
| + choose_another_service_link_->SetText(l10n_util::GetStringUTF16(
|
| + IDS_INTENT_PICKER_USE_ALTERNATE_SERVICE));
|
| + choose_another_service_link_->set_listener(this);
|
| +
|
| + grid_layout->AddView(CreateInlineDispositionHeader(
|
| + inline_service_icon_, title, choose_another_service_link_));
|
| + choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model_));
|
| +
|
| + views::ImageButton* close_button = CreateCloseButton(this);
|
| + grid_layout->AddView(close_button);
|
| + close_button->SetVisible(use_close_button_);
|
| +
|
| + // Separator.
|
| + const int kHeaderBuiltinBottomPadding = 4;
|
| + grid_layout->AddPaddingRow(0,
|
| + ConstrainedWindowConstants::kRowPadding -
|
| + kHeaderBuiltinBottomPadding);
|
| + grid_layout->StartRow(0, SEPARATOR_ROW);
|
| + grid_layout->AddView(new views::Separator());
|
| +
|
| + // Inline web contents.
|
| + const int kSeparatorBottomPadding = 3;
|
| + grid_layout->AddPaddingRow(0, kSeparatorBottomPadding);
|
| + grid_layout->StartRow(0, WEB_CONTENTS_ROW);
|
| + grid_layout->AddView(webview_);
|
|
|
| - // Inline web contents row.
|
| - grid_layout->StartRow(0, 1);
|
| - grid_layout->AddView(webview_, 1, 1, GridLayout::CENTER,
|
| - GridLayout::CENTER, 0, 0);
|
| contents_->Layout();
|
| SizeToContents();
|
| - displaying_web_contents_ = true;
|
| }
|
|
|
| void WebIntentPickerViews::OnModelChanged(WebIntentPickerModel* model) {
|
| - if (waiting_view_ && !model->IsWaitingForSuggestions())
|
| + if (state_ == WAITING && !model->IsWaitingForSuggestions())
|
| UpdateContents();
|
|
|
| - if (suggestions_label_) {
|
| - string16 label_text = model->GetSuggestionsLinkText();
|
| - suggestions_label_->SetText(label_text);
|
| - suggestions_label_->SetVisible(!label_text.empty());
|
| + if (choose_another_service_link_) {
|
| + choose_another_service_link_->SetVisible(IsUseAnotherServiceVisible(model));
|
| + contents_->Layout();
|
| + SizeToContents();
|
| }
|
|
|
| if (extensions_)
|
| - extensions_->Update();
|
| - contents_->Layout();
|
| - SizeToContents();
|
| + RefreshExtensions();
|
| }
|
|
|
| void WebIntentPickerViews::OnFaviconChanged(WebIntentPickerModel* model,
|
| size_t index) {
|
| // TODO(groby): Update favicons on extensions_;
|
| - contents_->Layout();
|
| - SizeToContents();
|
| + if (inline_service_icon_)
|
| + RefreshInlineServiceIcon();
|
| + if (extensions_)
|
| + RefreshExtensions();
|
| }
|
|
|
| void WebIntentPickerViews::OnExtensionIconChanged(
|
| WebIntentPickerModel* model,
|
| const std::string& extension_id) {
|
| - if (extensions_)
|
| - extensions_->Update();
|
| -
|
| - contents_->Layout();
|
| - SizeToContents();
|
| + OnFaviconChanged(model, -1);
|
| }
|
|
|
| void WebIntentPickerViews::OnInlineDisposition(
|
| @@ -1235,13 +1425,7 @@ void WebIntentPickerViews::UpdateContents() {
|
| return;
|
|
|
| if (model_ && model_->IsWaitingForSuggestions()) {
|
| - ClearContents();
|
| - contents_->SetLayoutManager(new views::FillLayout());
|
| - waiting_view_ = new WaitingView(this, use_close_button_);
|
| - contents_->AddChildView(waiting_view_);
|
| - int height = contents_->GetHeightForWidth(kWindowMinWidth);
|
| - contents_->SetSize(gfx::Size(kWindowMinWidth, height));
|
| - contents_->Layout();
|
| + ShowWaitingForSuggestions();
|
| } else if (model_ && (model_->GetInstalledServiceCount() ||
|
| model_->GetSuggestedExtensionCount())) {
|
| ShowAvailableServices();
|
| @@ -1251,99 +1435,105 @@ void WebIntentPickerViews::UpdateContents() {
|
| SizeToContents();
|
| }
|
|
|
| +void WebIntentPickerViews::ShowWaitingForSuggestions() {
|
| + if (state_ == WAITING)
|
| + return;
|
| + state_ = WAITING;
|
| + ClearContents();
|
| + contents_->SetLayoutManager(new views::FillLayout());
|
| + waiting_view_ = new WaitingView(this, use_close_button_);
|
| + contents_->AddChildView(waiting_view_);
|
| + int height = contents_->GetHeightForWidth(kWindowMinWidth);
|
| + contents_->SetSize(gfx::Size(kWindowMinWidth, height));
|
| + contents_->Layout();
|
| +}
|
| +
|
| const string16 WebIntentPickerViews::GetActionTitle() {
|
| - return (!action_text_.empty()) ?
|
| - action_text_ :
|
| - l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE);
|
| + return action_text_.empty() ?
|
| + l10n_util::GetStringUTF16(IDS_INTENT_PICKER_CHOOSE_SERVICE) :
|
| + action_text_;
|
| }
|
|
|
| void WebIntentPickerViews::ShowAvailableServices() {
|
| - enum {
|
| - kHeaderRowColumnSet, // Column set for header layout.
|
| - kFullWidthColumnSet, // Column set with a single full-width column.
|
| - kIndentedFullWidthColumnSet, // Single full-width column, indented.
|
| - };
|
| -
|
| ClearContents();
|
| - displaying_web_contents_ = false;
|
| -
|
| + state_ = LIST_SERVICES;
|
| extensions_ = new IntentsView(model_, this);
|
| + gfx::Size min_size = gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0);
|
|
|
| views::GridLayout* grid_layout = new views::GridLayout(contents_);
|
| + grid_layout->set_minimum_size(min_size);
|
| + const int kIconBuiltinBottomPadding = 4;
|
| + grid_layout->SetInsets(ConstrainedWindowConstants::kCloseButtonPadding,
|
| + 0,
|
| + ConstrainedWindowConstants::kClientBottomPadding -
|
| + kIconBuiltinBottomPadding,
|
| + 0);
|
| contents_->SetLayoutManager(grid_layout);
|
|
|
| - grid_layout->set_minimum_size(
|
| - gfx::Size(extensions_->AdjustWidth(kWindowMinWidth), 0));
|
| - grid_layout->SetInsets(kContentAreaBorder, kContentAreaBorder,
|
| - kContentAreaBorder, kContentAreaBorder);
|
| - views::ColumnSet* header_cs = grid_layout->AddColumnSet(kHeaderRowColumnSet);
|
| + enum GridLayoutColumnSets {
|
| + HEADER_ROW,
|
| + CONTENT_ROW,
|
| + };
|
| + views::ColumnSet* header_cs = grid_layout->AddColumnSet(HEADER_ROW);
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| header_cs->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0); // Title.
|
| - if (use_close_button_) {
|
| - header_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
|
| - header_cs->AddColumn(GridLayout::CENTER, GridLayout::CENTER, 0,
|
| - GridLayout::USE_PREF, 0, 0); // Close Button.
|
| - }
|
| -
|
| - views::ColumnSet* full_cs = grid_layout->AddColumnSet(kFullWidthColumnSet);
|
| - full_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0);
|
| -
|
| - views::ColumnSet* indent_cs =
|
| - grid_layout->AddColumnSet(kIndentedFullWidthColumnSet);
|
| - indent_cs->AddPaddingColumn(0, views::kUnrelatedControlHorizontalSpacing);
|
| - indent_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| - GridLayout::USE_PREF, 0, 0);
|
| -
|
| - ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
|
| -
|
| - // Header row.
|
| - grid_layout->StartRow(0, kHeaderRowColumnSet);
|
| - action_label_ = new views::Label(GetActionTitle());
|
| - action_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| - action_label_->SetFont(rb.GetFont(ui::ResourceBundle::MediumFont));
|
| + GridLayout::USE_PREF, 0, 0); // Action title
|
| + header_cs->AddColumn(GridLayout::TRAILING, GridLayout::LEADING, 0,
|
| + GridLayout::USE_PREF, 0, 0); // Close button
|
| + header_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kCloseButtonPadding);
|
| +
|
| + views::ColumnSet* content_cs = grid_layout->AddColumnSet(CONTENT_ROW);
|
| + content_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| + content_cs->AddColumn(GridLayout::FILL, GridLayout::CENTER, 1,
|
| + GridLayout::USE_PREF, 0, 0); // Content.
|
| + content_cs->AddPaddingColumn(
|
| + 0, ConstrainedWindowConstants::kHorizontalPadding);
|
| +
|
| + // Header.
|
| + grid_layout->StartRow(0, HEADER_ROW);
|
| + if (!action_label_)
|
| + action_label_ = CreateTitleLabel();
|
| + action_label_->SetText(GetActionTitle());
|
| grid_layout->AddView(action_label_);
|
|
|
| - if (use_close_button_)
|
| - grid_layout->AddView(CreateCloseButton(this));
|
| -
|
| - // Padding row.
|
| - grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
|
| + views::ImageButton* close_button = CreateCloseButton(this);
|
| + grid_layout->AddView(close_button);
|
| + close_button->SetVisible(use_close_button_);
|
|
|
| - // Row with app suggestions label.
|
| - grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
|
| - suggestions_label_ = new views::Label();
|
| - suggestions_label_->SetVisible(false);
|
| - suggestions_label_->SetMultiLine(true);
|
| - suggestions_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| - grid_layout->AddView(suggestions_label_);
|
| -
|
| - // Padding row.
|
| - grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
|
| -
|
| - // Row with extension suggestions.
|
| - grid_layout->StartRow(0, kIndentedFullWidthColumnSet);
|
| + // Extensions.
|
| + const int kHeaderBuiltinBottomPadding = 4;
|
| + grid_layout->AddPaddingRow(0,
|
| + ConstrainedWindowConstants::kRowPadding -
|
| + kHeaderBuiltinBottomPadding);
|
| + grid_layout->StartRow(0, CONTENT_ROW);
|
| grid_layout->AddView(extensions_);
|
|
|
| - // Padding row.
|
| - grid_layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
|
|
|
| // Row with "more suggestions" link.
|
| - grid_layout->StartRow(0, kFullWidthColumnSet);
|
| + const int kIconBuiltinTopPadding = 6;
|
| + grid_layout->AddPaddingRow(0,
|
| + ConstrainedWindowConstants::kRowPadding -
|
| + kIconBuiltinTopPadding);
|
| + grid_layout->StartRow(0, CONTENT_ROW);
|
| views::View* more_view = new views::View();
|
| - more_view->SetLayoutManager(
|
| - new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0,
|
| - views::kRelatedControlHorizontalSpacing));
|
| + more_view->SetLayoutManager(new views::BoxLayout(
|
| + views::BoxLayout::kHorizontal, 0, 0, kIconTextPadding));
|
| views::ImageView* icon = new views::ImageView();
|
| - icon->SetImage(rb.GetImageNamed(IDR_WEBSTORE_ICON_16).ToImageSkia());
|
| + icon->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
|
| + IDR_WEBSTORE_ICON_16));
|
| more_view->AddChildView(icon);
|
| - more_suggestions_link_ = new views::Link(
|
| - l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
|
| - more_suggestions_link_->SetDisabledColor(kDisabledLinkColor);
|
| + if (!more_suggestions_link_)
|
| + more_suggestions_link_ = CreateLink();
|
| + more_suggestions_link_->SetText(
|
| + l10n_util::GetStringUTF16(IDS_FIND_MORE_INTENT_HANDLER_MESSAGE));
|
| more_suggestions_link_->set_listener(this);
|
| more_view->AddChildView(more_suggestions_link_);
|
| grid_layout->AddView(more_view, 1, 1,
|
| GridLayout::LEADING, GridLayout::CENTER);
|
| +
|
| contents_->Layout();
|
| }
|
|
|
| @@ -1357,8 +1547,10 @@ void WebIntentPickerViews::ResetContents() {
|
| UpdateContents();
|
|
|
| // Restore previous state.
|
| - extensions_->Update();
|
| - action_label_->SetText(action_text_);
|
| + if (extensions_)
|
| + extensions_->Update();
|
| + if (action_label_)
|
| + action_label_->SetText(action_text_);
|
| contents_->Layout();
|
| SizeToContents();
|
| }
|
| @@ -1379,8 +1571,23 @@ void WebIntentPickerViews::ClearContents() {
|
| // would cause hard-to-explain crashes.
|
| contents_->RemoveAllChildViews(true);
|
| action_label_ = NULL;
|
| - suggestions_label_ = NULL;
|
| extensions_ = NULL;
|
| more_suggestions_link_ = NULL;
|
| + inline_service_icon_ = NULL;
|
| choose_another_service_link_ = NULL;
|
| }
|
| +
|
| +void WebIntentPickerViews::RefreshInlineServiceIcon() {
|
| + DCHECK(inline_service_icon_);
|
| + const WebIntentPickerModel::InstalledService* inline_service =
|
| + model_->GetInstalledServiceWithURL(model_->inline_disposition_url());
|
| + if (inline_service)
|
| + inline_service_icon_->SetImage(inline_service->favicon.ToImageSkia());
|
| +}
|
| +
|
| +void WebIntentPickerViews::RefreshExtensions() {
|
| + DCHECK(extensions_);
|
| + extensions_->Update();
|
| + contents_->Layout();
|
| + SizeToContents();
|
| +}
|
|
|