| Index: chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
|
| diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
|
| index 15216d8b9ed83b665ce6a2d90602b4b40644747b..9eb58c7bc34e3b2b05a5ba963ae79ce3dc738dd5 100644
|
| --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
|
| +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
|
| @@ -15,8 +15,13 @@
|
| #include "chrome/common/extensions/extension.h"
|
| #include "content/public/browser/page_navigator.h"
|
| #include "grit/generated_resources.h"
|
| +#include "grit/theme_resources.h"
|
| +#include "ui/base/animation/animation_delegate.h"
|
| +#include "ui/base/animation/slide_animation.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #include "ui/base/resource/resource_bundle.h"
|
| +#include "ui/gfx/point3.h"
|
| +#include "ui/gfx/transform.h"
|
| #include "ui/views/border.h"
|
| #include "ui/views/controls/image_view.h"
|
| #include "ui/views/controls/label.h"
|
| @@ -67,7 +72,13 @@ void AddResourceIcon(const gfx::ImageSkia* skia_image, void* data) {
|
| parent->AddChildView(image_view);
|
| }
|
|
|
| -} // namespace
|
| +// Creates a string for displaying |message| to the user. If it has to look
|
| +// like a entry in a bullet point list, one is added.
|
| +string16 PrepareForDisplay(const string16& message, bool bullet_point) {
|
| + return bullet_point ? l10n_util::GetStringFUTF16(
|
| + IDS_EXTENSION_PERMISSION_LINE,
|
| + message) : message;
|
| +}
|
|
|
| // Implements the extension installation dialog for TOOLKIT_VIEWS.
|
| class ExtensionInstallDialogView : public views::DialogDelegateView,
|
| @@ -78,6 +89,10 @@ class ExtensionInstallDialogView : public views::DialogDelegateView,
|
| const ExtensionInstallPrompt::Prompt& prompt);
|
| virtual ~ExtensionInstallDialogView();
|
|
|
| + // Changes the size of the containing widget to match the preferred size
|
| + // of this dialog.
|
| + void SizeToContents();
|
| +
|
| private:
|
| // views::DialogDelegateView:
|
| virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
|
| @@ -108,6 +123,61 @@ class ExtensionInstallDialogView : public views::DialogDelegateView,
|
| DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView);
|
| };
|
|
|
| +// A view to display a single IssueAdviceInfoEntry.
|
| +class IssueAdviceView : public views::View,
|
| + public ui::AnimationDelegate {
|
| + public:
|
| + IssueAdviceView(ExtensionInstallDialogView* owner,
|
| + const IssueAdviceInfoEntry& issue_advice,
|
| + int horizontal_space);
|
| + virtual ~IssueAdviceView() {}
|
| +
|
| + // Implementation of views::View:
|
| + virtual bool OnMousePressed(const views::MouseEvent& event) OVERRIDE;
|
| + virtual void OnMouseReleased(const views::MouseEvent& event) OVERRIDE;
|
| + virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE;
|
| +
|
| + // Implementation of ui::AnimationDelegate:
|
| + virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE;
|
| +
|
| + private:
|
| + // A view which displays all the details of an IssueAdviceInfoEntry.
|
| + class DetailsView : public views::View {
|
| + public:
|
| + explicit DetailsView(int horizontal_space);
|
| + virtual ~DetailsView() {}
|
| +
|
| + // Implementation of views::View:
|
| + virtual gfx::Size GetPreferredSize() OVERRIDE;
|
| +
|
| + void AddDetail(const string16& detail);
|
| +
|
| + // Animates this to be a height proportional to |state|.
|
| + void AnimateToState(double state);
|
| +
|
| + private:
|
| + views::GridLayout* layout_;
|
| + double state_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(DetailsView);
|
| + };
|
| +
|
| + // The dialog that owns |this|. It's also an ancestor in the View hierarchy.
|
| + ExtensionInstallDialogView* owner_;
|
| +
|
| + // A view for showing |issue_advice.details|.
|
| + DetailsView* details_view_;
|
| +
|
| + // The '>' zippy control.
|
| + views::ImageView* arrow_view_;
|
| +
|
| + ui::SlideAnimation slide_animation_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(IssueAdviceView);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| content::PageNavigator* navigator,
|
| ExtensionInstallPrompt::Delegate* delegate,
|
| @@ -137,7 +207,7 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| // +--------------------+------+
|
| //
|
| // Regular install
|
| - // w/ permissions no permissions
|
| + // w/ permissions XOR oauth issues no permissions
|
| // +--------------------+------+ +--------------+------+
|
| // | heading | icon | | heading | icon |
|
| // +--------------------| | +--------------+------+
|
| @@ -147,6 +217,23 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| // +--------------------| |
|
| // | permission2 | |
|
| // +--------------------+------+
|
| + //
|
| + // w/ permissions AND oauth issues
|
| + // +--------------------+------+
|
| + // | heading | icon |
|
| + // +--------------------| |
|
| + // | permissions_header | |
|
| + // +--------------------| |
|
| + // | permission1 | |
|
| + // +--------------------| |
|
| + // | permission2 | |
|
| + // +--------------------+------+
|
| + // | oauth header |
|
| + // +---------------------------+
|
| + // | oauth issue 1 |
|
| + // +---------------------------+
|
| + // | oauth issue 2 |
|
| + // +---------------------------+
|
|
|
| views::GridLayout* layout = views::GridLayout::CreatePanel(this);
|
| SetLayoutManager(layout);
|
| @@ -162,7 +249,7 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| views::GridLayout::FILL,
|
| 0, // no resizing
|
| views::GridLayout::USE_PREF,
|
| - 0, // no fixed with
|
| + 0, // no fixed width
|
| left_column_width);
|
| if (!is_bundle_install()) {
|
| column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
|
| @@ -203,6 +290,10 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| // Also span the permission header and each of the permission rows (all
|
| // have a padding row above it).
|
| icon_row_span = 3 + prompt.GetPermissionCount() * 2;
|
| + } else if (prompt.GetOAuthIssueCount()) {
|
| + // Also span the permission header and each of the permission rows (all
|
| + // have a padding row above it).
|
| + icon_row_span = 3 + prompt.GetOAuthIssueCount() * 2;
|
| }
|
| layout->AddView(icon, 1, icon_row_span);
|
| }
|
| @@ -246,8 +337,7 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
|
| layout->StartRow(0, column_set_id);
|
| views::Label* extension_label = new views::Label(
|
| - l10n_util::GetStringFUTF16(
|
| - IDS_EXTENSION_PERMISSION_LINE, extension_name));
|
| + PrepareForDisplay(extension_name, true));
|
| extension_label->SetMultiLine(true);
|
| extension_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| extension_label->SizeToFit(left_column_width);
|
| @@ -294,11 +384,49 @@ ExtensionInstallDialogView::ExtensionInstallDialogView(
|
| layout->AddView(permission_label);
|
| }
|
| }
|
| +
|
| + if (prompt.GetOAuthIssueCount()) {
|
| + // Slide in under the permissions; stretch all the way to the right of the
|
| + // dialog.
|
| + int space_for_oauth = left_column_width;
|
| + if (prompt.GetPermissionCount()) {
|
| + space_for_oauth += kIconSize;
|
| + column_set = layout->AddColumnSet(++column_set_id);
|
| + column_set->AddColumn(views::GridLayout::FILL,
|
| + views::GridLayout::FILL,
|
| + 1,
|
| + views::GridLayout::USE_PREF,
|
| + 0, // no fixed width
|
| + space_for_oauth);
|
| + }
|
| +
|
| + layout->StartRowWithPadding(0, column_set_id,
|
| + 0, views::kRelatedControlVerticalSpacing);
|
| + views::Label* oauth_header = new views::Label(prompt.GetOAuthHeading());
|
| + oauth_header->SetMultiLine(true);
|
| + oauth_header->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + oauth_header->SizeToFit(left_column_width);
|
| + layout->AddView(oauth_header);
|
| +
|
| + for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) {
|
| + layout->StartRowWithPadding(
|
| + 0, column_set_id,
|
| + 0, views::kRelatedControlVerticalSpacing);
|
| +
|
| + IssueAdviceView* issue_advice_view =
|
| + new IssueAdviceView(this, prompt.GetOAuthIssue(i), space_for_oauth);
|
| + layout->AddView(issue_advice_view);
|
| + }
|
| + }
|
| }
|
|
|
| ExtensionInstallDialogView::~ExtensionInstallDialogView() {
|
| }
|
|
|
| +void ExtensionInstallDialogView::SizeToContents() {
|
| + GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize());
|
| +}
|
| +
|
| string16 ExtensionInstallDialogView::GetDialogButtonLabel(
|
| ui::DialogButton button) const {
|
| switch (button) {
|
| @@ -360,3 +488,136 @@ void ShowExtensionInstallDialogImpl(
|
| new ExtensionInstallDialogView(navigator, delegate, prompt),
|
| parent)->Show();
|
| }
|
| +
|
| +// IssueAdviceView::DetailsView ------------------------------------------------
|
| +
|
| +IssueAdviceView::DetailsView::DetailsView(int horizontal_space)
|
| + : layout_(new views::GridLayout(this)),
|
| + state_(0) {
|
| + SetLayoutManager(layout_);
|
| + views::ColumnSet* column_set = layout_->AddColumnSet(0);
|
| + column_set->AddColumn(views::GridLayout::LEADING,
|
| + views::GridLayout::LEADING,
|
| + 0,
|
| + views::GridLayout::FIXED,
|
| + horizontal_space,
|
| + 0);
|
| +}
|
| +
|
| +void IssueAdviceView::DetailsView::AddDetail(const string16& detail) {
|
| + layout_->StartRowWithPadding(0, 0,
|
| + 0, views::kRelatedControlSmallVerticalSpacing);
|
| + views::Label* detail_label =
|
| + new views::Label(PrepareForDisplay(detail, true));
|
| + detail_label->SetMultiLine(true);
|
| + detail_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + layout_->AddView(detail_label);
|
| +}
|
| +
|
| +gfx::Size IssueAdviceView::DetailsView::GetPreferredSize() {
|
| + gfx::Size size = views::View::GetPreferredSize();
|
| + return gfx::Size(size.width(), size.height() * state_);
|
| +}
|
| +
|
| +void IssueAdviceView::DetailsView::AnimateToState(double state) {
|
| + state_ = state;
|
| + PreferredSizeChanged();
|
| + SchedulePaint();
|
| +}
|
| +
|
| +// IssueAdviceView -------------------------------------------------------------
|
| +
|
| +IssueAdviceView::IssueAdviceView(ExtensionInstallDialogView* owner,
|
| + const IssueAdviceInfoEntry& issue_advice,
|
| + int horizontal_space)
|
| + : owner_(owner),
|
| + details_view_(NULL),
|
| + arrow_view_(NULL),
|
| + slide_animation_(this) {
|
| + // TODO(estade): replace this with a more appropriate image.
|
| + const gfx::ImageSkia& image = *ui::ResourceBundle::GetSharedInstance().
|
| + GetImageSkiaNamed(IDR_OMNIBOX_TTS);
|
| +
|
| + views::GridLayout* layout = new views::GridLayout(this);
|
| + SetLayoutManager(layout);
|
| + int column_set_id = 0;
|
| + views::ColumnSet* column_set = layout->AddColumnSet(column_set_id);
|
| + if (!issue_advice.details.empty()) {
|
| + column_set->AddColumn(views::GridLayout::LEADING,
|
| + views::GridLayout::LEADING,
|
| + 0,
|
| + views::GridLayout::FIXED,
|
| + image.width(),
|
| + 0);
|
| + horizontal_space -= image.width();
|
| + details_view_ = new DetailsView(horizontal_space);
|
| + }
|
| + column_set->AddColumn(views::GridLayout::LEADING,
|
| + views::GridLayout::FILL,
|
| + 0,
|
| + views::GridLayout::FIXED,
|
| + horizontal_space,
|
| + 0);
|
| + layout->StartRow(0, column_set_id);
|
| +
|
| + if (details_view_) {
|
| + arrow_view_ = new views::ImageView();
|
| + arrow_view_->SetImage(image);
|
| + arrow_view_->SetVerticalAlignment(views::ImageView::CENTER);
|
| + layout->AddView(arrow_view_);
|
| + }
|
| +
|
| + views::Label* description_label =
|
| + new views::Label(PrepareForDisplay(issue_advice.description,
|
| + !details_view_));
|
| + description_label->SetMultiLine(true);
|
| + description_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
|
| + description_label->SizeToFit(horizontal_space);
|
| + layout->AddView(description_label);
|
| +
|
| + if (!details_view_)
|
| + return;
|
| +
|
| + layout->StartRow(0, column_set_id);
|
| + layout->SkipColumns(1);
|
| + layout->AddView(details_view_);
|
| +
|
| + for (size_t i = 0; i < issue_advice.details.size(); ++i)
|
| + details_view_->AddDetail(issue_advice.details[i]);
|
| +}
|
| +
|
| +bool IssueAdviceView::OnMousePressed(const views::MouseEvent& event) {
|
| + return details_view_ && event.IsLeftMouseButton();
|
| +}
|
| +
|
| +void IssueAdviceView::OnMouseReleased(const views::MouseEvent& event) {
|
| + if (slide_animation_.IsShowing())
|
| + slide_animation_.Hide();
|
| + else
|
| + slide_animation_.Show();
|
| +}
|
| +
|
| +void IssueAdviceView::AnimationProgressed(const ui::Animation* animation) {
|
| + DCHECK_EQ(animation, &slide_animation_);
|
| +
|
| + if (details_view_)
|
| + details_view_->AnimateToState(animation->GetCurrentValue());
|
| +
|
| + if (arrow_view_) {
|
| + ui::Transform rotate;
|
| + if (animation->GetCurrentValue() != 0.0) {
|
| + rotate.SetTranslate(-arrow_view_->width() / 2.0,
|
| + -arrow_view_->height() / 2.0);
|
| + // TODO(estade): for some reason there are rendering errors at 90 degrees.
|
| + // Figure out why.
|
| + rotate.ConcatRotate(animation->GetCurrentValue() * 89);
|
| + rotate.ConcatTranslate(arrow_view_->width() / 2.0,
|
| + arrow_view_->height() / 2.0);
|
| + }
|
| + arrow_view_->SetTransform(rotate);
|
| + }
|
| +}
|
| +
|
| +void IssueAdviceView::ChildPreferredSizeChanged(views::View* child) {
|
| + owner_->SizeToContents();
|
| +}
|
|
|