Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 #include "grit/chromium_strings.h" | 22 #include "grit/chromium_strings.h" |
| 23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
| 24 #include "grit/google_chrome_strings.h" | 24 #include "grit/google_chrome_strings.h" |
| 25 #include "grit/theme_resources.h" | 25 #include "grit/theme_resources.h" |
| 26 #include "ui/base/animation/animation_delegate.h" | 26 #include "ui/base/animation/animation_delegate.h" |
| 27 #include "ui/base/animation/slide_animation.h" | 27 #include "ui/base/animation/slide_animation.h" |
| 28 #include "ui/base/l10n/l10n_util.h" | 28 #include "ui/base/l10n/l10n_util.h" |
| 29 #include "ui/base/resource/resource_bundle.h" | 29 #include "ui/base/resource/resource_bundle.h" |
| 30 #include "ui/gfx/transform.h" | 30 #include "ui/gfx/transform.h" |
| 31 #include "ui/views/border.h" | 31 #include "ui/views/border.h" |
| 32 #include "ui/views/controls/button/image_button.h" | |
| 32 #include "ui/views/controls/image_view.h" | 33 #include "ui/views/controls/image_view.h" |
| 33 #include "ui/views/controls/label.h" | 34 #include "ui/views/controls/label.h" |
| 34 #include "ui/views/controls/link.h" | 35 #include "ui/views/controls/link.h" |
| 35 #include "ui/views/controls/link_listener.h" | 36 #include "ui/views/controls/link_listener.h" |
| 36 #include "ui/views/controls/scroll_view.h" | 37 #include "ui/views/controls/scroll_view.h" |
| 37 #include "ui/views/controls/separator.h" | 38 #include "ui/views/controls/separator.h" |
| 38 #include "ui/views/layout/box_layout.h" | 39 #include "ui/views/layout/box_layout.h" |
| 39 #include "ui/views/layout/grid_layout.h" | 40 #include "ui/views/layout/grid_layout.h" |
| 40 #include "ui/views/layout/layout_constants.h" | 41 #include "ui/views/layout/layout_constants.h" |
| 41 #include "ui/views/view.h" | 42 #include "ui/views/view.h" |
| 42 #include "ui/views/widget/widget.h" | 43 #include "ui/views/widget/widget.h" |
| 43 #include "ui/views/window/dialog_delegate.h" | 44 #include "ui/views/window/dialog_delegate.h" |
| 44 | 45 |
| 45 using content::OpenURLParams; | 46 using content::OpenURLParams; |
| 46 using content::Referrer; | 47 using content::Referrer; |
| 47 using extensions::BundleInstaller; | 48 using extensions::BundleInstaller; |
| 48 | 49 |
| 49 namespace { | 50 namespace { |
| 50 | 51 |
| 51 // Size of extension icon in top left of dialog. | 52 // Size of extension icon in top left of dialog. |
| 52 const int kIconSize = 69; | 53 const int kIconSize = 69; |
| 53 | 54 |
| 55 // The dialog width. | |
| 56 const int kDialogWidth = 385; | |
| 57 | |
| 58 // The dialog will resize based on its content, but this sets a maximum height | |
| 59 // before overflowing a scrollbar. | |
| 60 const int kDialogMaxHeight = 300; | |
| 61 | |
| 54 // Width of the left column of the dialog when the extension requests | 62 // Width of the left column of the dialog when the extension requests |
| 55 // permissions. | 63 // permissions. |
| 56 const int kPermissionsLeftColumnWidth = 250; | 64 const int kPermissionsLeftColumnWidth = 250; |
| 57 | 65 |
| 58 // Width of the left column of the dialog when the extension requests no | 66 // Width of the left column of the dialog when the extension requests no |
| 59 // permissions. | 67 // permissions. |
| 60 const int kNoPermissionsLeftColumnWidth = 200; | 68 const int kNoPermissionsLeftColumnWidth = 200; |
| 61 | 69 |
| 62 // Width of the left column for bundle install prompts. There's only one column | 70 // Width of the left column for bundle install prompts. There's only one column |
| 63 // in this case, so make it wider than normal. | 71 // in this case, so make it wider than normal. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 87 | 95 |
| 88 // Implements the extension installation dialog for TOOLKIT_VIEWS. | 96 // Implements the extension installation dialog for TOOLKIT_VIEWS. |
| 89 class ExtensionInstallDialogView : public views::DialogDelegateView, | 97 class ExtensionInstallDialogView : public views::DialogDelegateView, |
| 90 public views::LinkListener { | 98 public views::LinkListener { |
| 91 public: | 99 public: |
| 92 ExtensionInstallDialogView(content::PageNavigator* navigator, | 100 ExtensionInstallDialogView(content::PageNavigator* navigator, |
| 93 ExtensionInstallPrompt::Delegate* delegate, | 101 ExtensionInstallPrompt::Delegate* delegate, |
| 94 const ExtensionInstallPrompt::Prompt& prompt); | 102 const ExtensionInstallPrompt::Prompt& prompt); |
| 95 virtual ~ExtensionInstallDialogView(); | 103 virtual ~ExtensionInstallDialogView(); |
| 96 | 104 |
| 97 // Changes the size of the containing widget to match the preferred size | 105 // Called when one of the child elements has expanded/collapsed. |
| 98 // of this dialog. | 106 void ContentsChanged(); |
| 99 void SizeToContents(); | |
| 100 | 107 |
| 101 private: | 108 private: |
| 102 // views::DialogDelegateView: | 109 // views::DialogDelegateView: |
| 103 virtual int GetDialogButtons() const OVERRIDE; | 110 virtual int GetDialogButtons() const OVERRIDE; |
| 104 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; | 111 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; |
| 105 virtual int GetDefaultDialogButton() const OVERRIDE; | 112 virtual int GetDefaultDialogButton() const OVERRIDE; |
| 106 virtual bool Cancel() OVERRIDE; | 113 virtual bool Cancel() OVERRIDE; |
| 107 virtual bool Accept() OVERRIDE; | 114 virtual bool Accept() OVERRIDE; |
| 108 | 115 |
| 109 // views::WidgetDelegate: | 116 // views::WidgetDelegate: |
| 110 virtual ui::ModalType GetModalType() const OVERRIDE; | 117 virtual ui::ModalType GetModalType() const OVERRIDE; |
| 111 virtual string16 GetWindowTitle() const OVERRIDE; | 118 virtual string16 GetWindowTitle() const OVERRIDE; |
| 112 | 119 |
| 113 // views::LinkListener: | 120 // views::LinkListener: |
| 114 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; | 121 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; |
| 115 | 122 |
| 123 // views::View: | |
| 124 virtual void Layout() OVERRIDE; | |
| 125 virtual gfx::Size GetPreferredSize() OVERRIDE; | |
| 126 | |
| 116 bool is_inline_install() const { | 127 bool is_inline_install() const { |
| 117 return prompt_.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; | 128 return prompt_.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT; |
| 118 } | 129 } |
| 119 | 130 |
| 120 bool is_bundle_install() const { | 131 bool is_bundle_install() const { |
| 121 return prompt_.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; | 132 return prompt_.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT; |
| 122 } | 133 } |
| 123 | 134 |
| 124 bool is_external_install() const { | 135 bool is_external_install() const { |
| 125 return prompt_.type() == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT; | 136 return prompt_.type() == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT; |
| 126 } | 137 } |
| 127 | 138 |
| 128 content::PageNavigator* navigator_; | 139 content::PageNavigator* navigator_; |
| 129 ExtensionInstallPrompt::Delegate* delegate_; | 140 ExtensionInstallPrompt::Delegate* delegate_; |
| 130 ExtensionInstallPrompt::Prompt prompt_; | 141 ExtensionInstallPrompt::Prompt prompt_; |
| 131 | 142 |
| 143 // The scroll view containing all the details for the dialog (including all | |
| 144 // collapsible/expandable sections). | |
| 145 views::ScrollView* scroll_view_; | |
| 146 | |
| 147 // The container view for the scroll view. | |
| 148 views::View* scrollable_; | |
| 149 | |
| 150 // The preferred size of the dialog. | |
| 151 gfx::Size dialog_size_; | |
| 152 | |
| 132 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); | 153 DISALLOW_COPY_AND_ASSIGN(ExtensionInstallDialogView); |
| 133 }; | 154 }; |
| 134 | 155 |
| 135 // A view to display a single IssueAdviceInfoEntry. | 156 // A view to display text with an expandable details section. |
| 136 class IssueAdviceView : public views::View, | 157 class ExpandableContainerView : public views::View, |
| 137 public ui::AnimationDelegate { | 158 public views::ButtonListener, |
| 159 public views::LinkListener, | |
| 160 public ui::AnimationDelegate { | |
| 138 public: | 161 public: |
| 139 IssueAdviceView(ExtensionInstallDialogView* owner, | 162 ExpandableContainerView(ExtensionInstallDialogView* owner, |
| 140 const IssueAdviceInfoEntry& issue_advice, | 163 const string16& description, |
| 141 int horizontal_space); | 164 const std::vector<string16>& details, |
| 142 virtual ~IssueAdviceView() {} | 165 int horizontal_space, |
| 166 bool show_bullets); | |
| 167 virtual ~ExpandableContainerView() {} | |
| 143 | 168 |
| 144 // Implementation of views::View: | 169 // Implementation of views::View: |
| 145 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; | |
| 146 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; | |
| 147 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; | 170 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; |
| 148 | 171 |
| 172 // views::ButtonListener: | |
| 173 virtual void ButtonPressed(views::Button* sender, | |
| 174 const ui::Event& event) OVERRIDE; | |
| 175 | |
| 176 // views::LinkListener: | |
| 177 virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; | |
| 178 | |
| 149 // Implementation of ui::AnimationDelegate: | 179 // Implementation of ui::AnimationDelegate: |
| 150 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; | 180 virtual void AnimationProgressed(const ui::Animation* animation) OVERRIDE; |
| 181 virtual void AnimationEnded(const ui::Animation* animation) OVERRIDE; | |
| 151 | 182 |
| 152 private: | 183 private: |
| 153 // A view which displays all the details of an IssueAdviceInfoEntry. | 184 // A view which displays all the details of an IssueAdviceInfoEntry. |
| 154 class DetailsView : public views::View { | 185 class DetailsView : public views::View { |
| 155 public: | 186 public: |
| 156 explicit DetailsView(int horizontal_space); | 187 explicit DetailsView(int horizontal_space, bool show_bullets); |
| 157 virtual ~DetailsView() {} | 188 virtual ~DetailsView() {} |
| 158 | 189 |
| 159 // Implementation of views::View: | 190 // Implementation of views::View: |
| 160 virtual gfx::Size GetPreferredSize() OVERRIDE; | 191 virtual gfx::Size GetPreferredSize() OVERRIDE; |
| 161 | 192 |
| 162 void AddDetail(const string16& detail); | 193 void AddDetail(const string16& detail); |
| 163 | 194 |
| 164 // Animates this to be a height proportional to |state|. | 195 // Animates this to be a height proportional to |state|. |
| 165 void AnimateToState(double state); | 196 void AnimateToState(double state); |
| 166 | 197 |
| 167 private: | 198 private: |
| 168 views::GridLayout* layout_; | 199 views::GridLayout* layout_; |
| 169 double state_; | 200 double state_; |
| 170 | 201 |
| 202 // Whether to show bullets in front of each item in the details. | |
| 203 bool show_bullets_; | |
| 204 | |
| 171 DISALLOW_COPY_AND_ASSIGN(DetailsView); | 205 DISALLOW_COPY_AND_ASSIGN(DetailsView); |
| 172 }; | 206 }; |
| 173 | 207 |
| 208 // Expand/Collapse the detail section for this ExpandableContainerView. | |
| 209 void ToggleDetailLevel(); | |
| 210 | |
| 174 // The dialog that owns |this|. It's also an ancestor in the View hierarchy. | 211 // The dialog that owns |this|. It's also an ancestor in the View hierarchy. |
| 175 ExtensionInstallDialogView* owner_; | 212 ExtensionInstallDialogView* owner_; |
| 176 | 213 |
| 177 // A view for showing |issue_advice.details|. | 214 // A view for showing |issue_advice.details|. |
| 178 DetailsView* details_view_; | 215 DetailsView* details_view_; |
| 179 | 216 |
| 180 // The '>' zippy control. | 217 // The '>' zippy control. |
| 181 views::ImageView* arrow_view_; | 218 views::ImageView* arrow_view_; |
| 182 | 219 |
| 183 ui::SlideAnimation slide_animation_; | 220 ui::SlideAnimation slide_animation_; |
| 184 | 221 |
| 185 DISALLOW_COPY_AND_ASSIGN(IssueAdviceView); | 222 // The 'more details' link shown under the heading (changes to 'hide details' |
| 223 // when the details section is expanded). | |
| 224 views::Link* more_details_; | |
| 225 | |
| 226 // The up/down arrow next to the 'more detail' link (points up/down depending | |
| 227 // on whether the details section is expanded). | |
| 228 views::ImageButton* arrow_toggle_; | |
| 229 | |
| 230 // Whether the details section is expanded. | |
| 231 bool expanded_; | |
| 232 | |
| 233 DISALLOW_COPY_AND_ASSIGN(ExpandableContainerView); | |
| 186 }; | 234 }; |
| 187 | 235 |
| 188 void ShowExtensionInstallDialogImpl( | 236 void ShowExtensionInstallDialogImpl( |
| 189 const ExtensionInstallPrompt::ShowParams& show_params, | 237 const ExtensionInstallPrompt::ShowParams& show_params, |
| 190 ExtensionInstallPrompt::Delegate* delegate, | 238 ExtensionInstallPrompt::Delegate* delegate, |
| 191 const ExtensionInstallPrompt::Prompt& prompt) { | 239 const ExtensionInstallPrompt::Prompt& prompt) { |
| 192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 240 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 193 CreateBrowserModalDialogViews( | 241 CreateBrowserModalDialogViews( |
| 194 new ExtensionInstallDialogView(show_params.navigator, delegate, prompt), | 242 new ExtensionInstallDialogView(show_params.navigator, delegate, prompt), |
| 195 show_params.parent_window)->Show(); | 243 show_params.parent_window)->Show(); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 // +--------------------| | | 329 // +--------------------| | |
| 282 // | permission2 | | | 330 // | permission2 | | |
| 283 // +--------------------+------+ | 331 // +--------------------+------+ |
| 284 // | oauth header | | 332 // | oauth header | |
| 285 // +---------------------------+ | 333 // +---------------------------+ |
| 286 // | oauth issue 1 | | 334 // | oauth issue 1 | |
| 287 // +---------------------------+ | 335 // +---------------------------+ |
| 288 // | oauth issue 2 | | 336 // | oauth issue 2 | |
| 289 // +---------------------------+ | 337 // +---------------------------+ |
| 290 | 338 |
| 291 views::GridLayout* layout = views::GridLayout::CreatePanel(this); | 339 scroll_view_ = new views::ScrollView(); |
| 292 SetLayoutManager(layout); | 340 AddChildView(scroll_view_); |
| 341 scrollable_ = new views::View(); | |
| 342 scroll_view_->SetContents(scrollable_); | |
| 343 | |
| 344 views::GridLayout* layout = views::GridLayout::CreatePanel(scrollable_); | |
| 345 scrollable_->SetLayoutManager(layout); | |
| 293 | 346 |
| 294 int column_set_id = 0; | 347 int column_set_id = 0; |
| 295 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); | 348 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); |
| 296 int left_column_width = | 349 int left_column_width = |
| 297 (prompt.ShouldShowPermissions() + prompt.GetOAuthIssueCount() + | 350 (prompt.ShouldShowPermissions() + prompt.GetOAuthIssueCount() + |
| 298 prompt.GetRetainedFileCount()) > 0 ? | 351 prompt.GetRetainedFileCount()) > 0 ? |
| 299 kPermissionsLeftColumnWidth : kNoPermissionsLeftColumnWidth; | 352 kPermissionsLeftColumnWidth : kNoPermissionsLeftColumnWidth; |
| 300 if (is_bundle_install()) | 353 if (is_bundle_install()) |
| 301 left_column_width = kBundleLeftColumnWidth; | 354 left_column_width = kBundleLeftColumnWidth; |
| 302 if (is_external_install()) | 355 if (is_external_install()) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 338 views::ImageView* icon = new views::ImageView(); | 391 views::ImageView* icon = new views::ImageView(); |
| 339 icon->SetImageSize(size); | 392 icon->SetImageSize(size); |
| 340 icon->SetImage(*image); | 393 icon->SetImage(*image); |
| 341 icon->SetHorizontalAlignment(views::ImageView::CENTER); | 394 icon->SetHorizontalAlignment(views::ImageView::CENTER); |
| 342 icon->SetVerticalAlignment(views::ImageView::CENTER); | 395 icon->SetVerticalAlignment(views::ImageView::CENTER); |
| 343 int icon_row_span = 1; | 396 int icon_row_span = 1; |
| 344 if (is_inline_install()) { | 397 if (is_inline_install()) { |
| 345 // Also span the rating, user_count and store_link rows. | 398 // Also span the rating, user_count and store_link rows. |
| 346 icon_row_span = 4; | 399 icon_row_span = 4; |
| 347 } else if (prompt.ShouldShowPermissions()) { | 400 } else if (prompt.ShouldShowPermissions()) { |
| 348 size_t permission_count = prompt.GetPermissionCount(); | 401 size_t permission_count = prompt.GetPermissionCount(true); |
| 349 if (permission_count > 0) { | 402 if (permission_count > 0) { |
| 350 // Also span the permission header and each of the permission rows (all | 403 // Also span the permission header and each of the permission rows (all |
| 351 // have a padding row above it). | 404 // have a padding row above it). |
| 352 icon_row_span = 3 + permission_count * 2; | 405 icon_row_span = 3 + permission_count * 2; |
| 353 } else { | 406 } else { |
| 354 // This is the 'no special permissions' case, so span the line we add | 407 // This is the 'no special permissions' case, so span the line we add |
| 355 // (without a header) saying the extension has no special privileges. | 408 // (without a header) saying the extension has no special privileges. |
| 356 icon_row_span = 4; | 409 icon_row_span = 4; |
| 357 } | 410 } |
| 358 } else if (prompt.GetOAuthIssueCount()) { | 411 } else if (prompt.GetOAuthIssueCount()) { |
| 359 // Also span the permission header and each of the permission rows (all | 412 // Also span the permission header and each of the permission rows (all |
| 360 // have a padding row above it). | 413 // have a padding row above it). |
| 361 icon_row_span = 3 + prompt.GetOAuthIssueCount() * 2; | 414 icon_row_span = 3 + prompt.GetOAuthIssueCount() * 2; |
| 362 } else if (prompt.GetRetainedFileCount()) { | 415 } else if (prompt.GetRetainedFileCount()) { |
| 363 // Also span the permission header and each of the permission rows (all | 416 // Also span the permission header and the retained files container. |
| 364 // have a padding row above it). | 417 icon_row_span = 4; |
| 365 icon_row_span = 3 + prompt.GetRetainedFileCount() * 2; | |
| 366 } | 418 } |
| 367 layout->AddView(icon, 1, icon_row_span); | 419 layout->AddView(icon, 1, icon_row_span); |
| 368 } | 420 } |
| 369 | 421 |
| 370 if (is_inline_install()) { | 422 if (is_inline_install()) { |
| 371 layout->StartRow(0, column_set_id); | 423 layout->StartRow(0, column_set_id); |
| 372 views::View* rating = new views::View(); | 424 views::View* rating = new views::View(); |
| 373 rating->SetLayoutManager(new views::BoxLayout( | 425 rating->SetLayoutManager(new views::BoxLayout( |
| 374 views::BoxLayout::kHorizontal, 0, 0, 0)); | 426 views::BoxLayout::kHorizontal, 0, 0, 0)); |
| 375 layout->AddView(rating); | 427 layout->AddView(rating); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 390 | 442 |
| 391 layout->StartRow(0, column_set_id); | 443 layout->StartRow(0, column_set_id); |
| 392 views::Link* store_link = new views::Link( | 444 views::Link* store_link = new views::Link( |
| 393 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK)); | 445 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_STORE_LINK)); |
| 394 store_link->SetFont(rb.GetFont(ui::ResourceBundle::SmallFont)); | 446 store_link->SetFont(rb.GetFont(ui::ResourceBundle::SmallFont)); |
| 395 store_link->set_listener(this); | 447 store_link->set_listener(this); |
| 396 layout->AddView(store_link); | 448 layout->AddView(store_link); |
| 397 } | 449 } |
| 398 | 450 |
| 399 if (is_bundle_install()) { | 451 if (is_bundle_install()) { |
| 400 BundleInstaller::ItemList items = prompt_.bundle()->GetItemsWithState( | 452 BundleInstaller::ItemList items = prompt.bundle()->GetItemsWithState( |
| 401 BundleInstaller::Item::STATE_PENDING); | 453 BundleInstaller::Item::STATE_PENDING); |
| 402 for (size_t i = 0; i < items.size(); ++i) { | 454 for (size_t i = 0; i < items.size(); ++i) { |
| 403 string16 extension_name = UTF8ToUTF16(items[i].localized_name); | 455 string16 extension_name = UTF8ToUTF16(items[i].localized_name); |
| 404 base::i18n::AdjustStringForLocaleDirection(&extension_name); | 456 base::i18n::AdjustStringForLocaleDirection(&extension_name); |
| 405 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 457 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 406 layout->StartRow(0, column_set_id); | 458 layout->StartRow(0, column_set_id); |
| 407 views::Label* extension_label = new views::Label( | 459 views::Label* extension_label = new views::Label( |
| 408 PrepareForDisplay(extension_name, true)); | 460 PrepareForDisplay(extension_name, true)); |
| 409 extension_label->SetMultiLine(true); | 461 extension_label->SetMultiLine(true); |
| 410 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 462 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 411 extension_label->SizeToFit(left_column_width); | 463 extension_label->SizeToFit(left_column_width); |
| 412 layout->AddView(extension_label); | 464 layout->AddView(extension_label); |
| 413 } | 465 } |
| 414 } | 466 } |
| 415 | 467 |
| 416 if (prompt.ShouldShowPermissions()) { | 468 if (prompt.ShouldShowPermissions()) { |
| 417 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 469 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 418 | 470 |
| 419 if (prompt.GetPermissionCount() > 0) { | 471 if (prompt.GetPermissionCount(true) > 0) { |
| 420 if (is_inline_install()) { | 472 if (is_inline_install()) { |
| 421 layout->StartRow(0, column_set_id); | 473 layout->StartRow(0, column_set_id); |
| 422 layout->AddView(new views::Separator(views::Separator::HORIZONTAL), | 474 layout->AddView(new views::Separator(views::Separator::HORIZONTAL), |
| 423 3, 1, views::GridLayout::FILL, views::GridLayout::FILL); | 475 3, 1, views::GridLayout::FILL, views::GridLayout::FILL); |
| 424 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 476 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 425 } | 477 } |
| 426 | 478 |
| 427 layout->StartRow(0, column_set_id); | 479 layout->StartRow(0, column_set_id); |
| 428 views::Label* permissions_header = NULL; | 480 views::Label* permissions_header = NULL; |
| 429 if (is_bundle_install()) { | 481 if (is_bundle_install()) { |
| 430 // We need to pass the Font in the constructor, rather than calling | 482 // We need to pass the Font in the constructor, rather than calling |
| 431 // SetFont later, because otherwise SizeToFit mis-judges the width | 483 // SetFont later, because otherwise SizeToFit mis-judges the width |
| 432 // of the line. | 484 // of the line. |
| 433 permissions_header = new views::Label( | 485 permissions_header = new views::Label( |
| 434 prompt.GetPermissionsHeading(), | 486 prompt.GetPermissionsHeading(), |
| 435 rb.GetFont(ui::ResourceBundle::MediumFont)); | 487 rb.GetFont(ui::ResourceBundle::MediumFont)); |
| 436 } else { | 488 } else { |
| 437 permissions_header = new views::Label(prompt.GetPermissionsHeading()); | 489 permissions_header = new views::Label(prompt.GetPermissionsHeading()); |
| 438 } | 490 } |
| 439 permissions_header->SetMultiLine(true); | 491 permissions_header->SetMultiLine(true); |
| 440 permissions_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 492 permissions_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 441 permissions_header->SizeToFit(left_column_width); | 493 permissions_header->SizeToFit(left_column_width); |
| 442 layout->AddView(permissions_header); | 494 layout->AddView(permissions_header); |
| 443 | 495 |
| 444 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { | 496 for (size_t i = 0; i < prompt.GetPermissionCount(false); ++i) { |
| 445 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 497 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 446 layout->StartRow(0, column_set_id); | 498 layout->StartRow(0, column_set_id); |
| 447 views::Label* permission_label = new views::Label(PrepareForDisplay( | 499 views::Label* permission_label = new views::Label(PrepareForDisplay( |
| 448 prompt.GetPermission(i), true)); | 500 prompt.GetPermission(i, false), true)); |
| 449 permission_label->SetMultiLine(true); | 501 permission_label->SetMultiLine(true); |
| 450 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 502 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 451 permission_label->SizeToFit(left_column_width); | 503 permission_label->SizeToFit(left_column_width); |
| 452 layout->AddView(permission_label); | 504 layout->AddView(permission_label); |
| 505 | |
| 506 // When the long for and short form differ, it means we have more | |
| 507 // details to provide, so show it unexpanded. | |
| 508 if (prompt.GetPermission(i, true) != prompt.GetPermission(i, false)) { | |
|
Yoyo Zhou
2013/07/10 23:18:58
These will differ whenever there is any host list.
| |
| 509 layout->StartRow(0, column_set_id); | |
| 510 std::vector<string16> details; | |
| 511 details.push_back( | |
| 512 PrepareForDisplay(prompt.GetPermission(i, true), false)); | |
| 513 ExpandableContainerView* details_container = | |
| 514 new ExpandableContainerView( | |
| 515 this, | |
| 516 string16(), | |
| 517 details, | |
| 518 left_column_width, | |
| 519 false); | |
| 520 layout->AddView(details_container); | |
| 521 } | |
| 453 } | 522 } |
| 454 } else { | 523 } else { |
| 455 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 524 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 456 layout->StartRow(0, column_set_id); | 525 layout->StartRow(0, column_set_id); |
| 457 views::Label* permission_label = new views::Label( | 526 views::Label* permission_label = new views::Label( |
| 458 l10n_util::GetStringUTF16(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS)); | 527 l10n_util::GetStringUTF16(IDS_EXTENSION_NO_SPECIAL_PERMISSIONS)); |
| 459 permission_label->SetMultiLine(true); | 528 permission_label->SetMultiLine(true); |
| 460 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 529 permission_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 461 permission_label->SizeToFit(left_column_width); | 530 permission_label->SizeToFit(left_column_width); |
| 462 layout->AddView(permission_label); | 531 layout->AddView(permission_label); |
| 463 } | 532 } |
| 464 } | 533 } |
| 465 | 534 |
| 466 if (prompt.GetOAuthIssueCount()) { | 535 if (prompt.GetOAuthIssueCount()) { |
| 467 // Slide in under the permissions, if there are any. If there are | 536 // Slide in under the permissions, if there are any. If there are |
| 468 // permissions, the OAuth prompt stretches all the way to the right of the | 537 // permissions, the OAuth prompt stretches all the way to the right of the |
| 469 // dialog. If there are no permissions, the OAuth prompt just takes up the | 538 // dialog. If there are no permissions, the OAuth prompt just takes up the |
| 470 // left column. | 539 // left column. |
| 471 int space_for_oauth = left_column_width; | 540 int space_for_oauth = left_column_width; |
| 472 if (prompt.GetPermissionCount()) { | 541 if (prompt.GetPermissionCount(true)) { |
| 473 space_for_oauth += kIconSize; | 542 space_for_oauth += kIconSize; |
| 474 column_set = layout->AddColumnSet(++column_set_id); | 543 column_set = layout->AddColumnSet(++column_set_id); |
| 475 column_set->AddColumn(views::GridLayout::FILL, | 544 column_set->AddColumn(views::GridLayout::FILL, |
| 476 views::GridLayout::FILL, | 545 views::GridLayout::FILL, |
| 477 1, | 546 1, |
| 478 views::GridLayout::USE_PREF, | 547 views::GridLayout::USE_PREF, |
| 479 0, // no fixed width | 548 0, // no fixed width |
| 480 space_for_oauth); | 549 space_for_oauth); |
| 481 } | 550 } |
| 482 | 551 |
| 483 layout->StartRowWithPadding(0, column_set_id, | 552 layout->StartRowWithPadding(0, column_set_id, |
| 484 0, views::kRelatedControlVerticalSpacing); | 553 0, views::kRelatedControlVerticalSpacing); |
| 485 views::Label* oauth_header = new views::Label(prompt.GetOAuthHeading()); | 554 views::Label* oauth_header = new views::Label(prompt.GetOAuthHeading()); |
| 486 oauth_header->SetMultiLine(true); | 555 oauth_header->SetMultiLine(true); |
| 487 oauth_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 556 oauth_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 488 oauth_header->SizeToFit(left_column_width); | 557 oauth_header->SizeToFit(left_column_width); |
| 489 layout->AddView(oauth_header); | 558 layout->AddView(oauth_header); |
| 490 | 559 |
| 491 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) { | 560 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) { |
| 492 layout->StartRowWithPadding( | 561 layout->StartRowWithPadding( |
| 493 0, column_set_id, | 562 0, column_set_id, |
| 494 0, views::kRelatedControlVerticalSpacing); | 563 0, views::kRelatedControlVerticalSpacing); |
| 495 | 564 |
| 496 IssueAdviceView* issue_advice_view = | 565 std::vector<string16> details; |
| 497 new IssueAdviceView(this, prompt.GetOAuthIssue(i), space_for_oauth); | 566 const IssueAdviceInfoEntry& entry = prompt.GetOAuthIssue(i); |
| 567 for (size_t x = 0; x < entry.details.size(); ++x) | |
| 568 details.push_back(entry.details[x]); | |
| 569 ExpandableContainerView* issue_advice_view = | |
| 570 new ExpandableContainerView( | |
| 571 this, | |
| 572 entry.description, | |
| 573 details, | |
| 574 space_for_oauth, | |
| 575 false); | |
| 498 layout->AddView(issue_advice_view); | 576 layout->AddView(issue_advice_view); |
| 499 } | 577 } |
| 500 } | 578 } |
| 501 if (prompt.GetRetainedFileCount()) { | 579 if (prompt.GetRetainedFileCount()) { |
| 502 // Slide in under the permissions or OAuth, if there are any. If there are | 580 // Slide in under the permissions or OAuth, if there are any. If there are |
| 503 // either, the retained files prompt stretches all the way to the right of | 581 // either, the retained files prompt stretches all the way to the right of |
| 504 // the dialog. If there are no permissions or OAuth, the retained files | 582 // the dialog. If there are no permissions or OAuth, the retained files |
| 505 // prompt just takes up the left column. | 583 // prompt just takes up the left column. |
| 506 int space_for_files = left_column_width; | 584 int space_for_files = left_column_width; |
| 507 if (prompt.GetPermissionCount() || prompt.GetOAuthIssueCount()) { | 585 if (prompt.GetPermissionCount(true) || prompt.GetOAuthIssueCount()) { |
| 508 space_for_files += kIconSize; | 586 space_for_files += kIconSize; |
| 509 column_set = layout->AddColumnSet(++column_set_id); | 587 column_set = layout->AddColumnSet(++column_set_id); |
| 510 column_set->AddColumn(views::GridLayout::FILL, | 588 column_set->AddColumn(views::GridLayout::FILL, |
| 511 views::GridLayout::FILL, | 589 views::GridLayout::FILL, |
| 512 1, | 590 1, |
| 513 views::GridLayout::USE_PREF, | 591 views::GridLayout::USE_PREF, |
| 514 0, // no fixed width | 592 0, // no fixed width |
| 515 space_for_files); | 593 space_for_files); |
| 516 } | 594 } |
| 517 | 595 |
| 518 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | 596 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); |
| 519 | 597 |
| 520 layout->StartRow(0, column_set_id); | 598 layout->StartRow(0, column_set_id); |
| 521 views::Label* retained_files_header = NULL; | 599 views::Label* retained_files_header = NULL; |
| 522 retained_files_header = new views::Label(prompt.GetRetainedFilesHeading()); | 600 retained_files_header = |
| 601 new views::Label(prompt.GetRetainedFilesHeadingWithCount()); | |
| 523 retained_files_header->SetMultiLine(true); | 602 retained_files_header->SetMultiLine(true); |
| 524 retained_files_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 603 retained_files_header->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 525 retained_files_header->SizeToFit(space_for_files); | 604 retained_files_header->SizeToFit(space_for_files); |
| 526 layout->AddView(retained_files_header); | 605 layout->AddView(retained_files_header); |
| 527 | 606 |
| 528 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); | |
| 529 layout->StartRow(0, column_set_id); | 607 layout->StartRow(0, column_set_id); |
| 530 views::View* files_view = new views::View(); | 608 std::vector<string16> details; |
| 531 files_view->SetLayoutManager(new views::BoxLayout( | 609 for (size_t i = 0; i < prompt.GetRetainedFileCount(); ++i) |
| 532 views::BoxLayout::kVertical, | 610 details.push_back(prompt.GetRetainedFile(i)); |
| 533 views::kRelatedControlHorizontalSpacing, | 611 ExpandableContainerView* issue_advice_view = |
| 534 0, | 612 new ExpandableContainerView( |
| 535 0)); | 613 this, |
| 536 for (size_t i = 0; i < prompt.GetRetainedFileCount(); ++i) { | 614 string16(), |
| 537 views::Label* retained_file_label = new views::Label(PrepareForDisplay( | 615 details, |
| 538 prompt.GetRetainedFile(i), true)); | 616 space_for_files, |
| 539 retained_file_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 617 false); |
| 540 files_view->AddChildView(retained_file_label); | 618 layout->AddView(issue_advice_view); |
| 541 } | |
| 542 views::ScrollView* scroll_view = | |
| 543 new MaxSizeScrollView(kMaxRetainedFilesHeight, space_for_files); | |
| 544 scroll_view->SetContents(files_view); | |
| 545 layout->AddView(scroll_view); | |
| 546 } | 619 } |
| 620 | |
| 621 gfx::Size scrollable_size = scrollable_->GetPreferredSize(); | |
| 622 scrollable_->SetBoundsRect(gfx::Rect(scrollable_size)); | |
| 623 dialog_size_ = gfx::Size( | |
| 624 kDialogWidth, | |
| 625 std::min(scrollable_size.height(), kDialogMaxHeight)); | |
| 547 } | 626 } |
| 548 | 627 |
| 549 ExtensionInstallDialogView::~ExtensionInstallDialogView() {} | 628 ExtensionInstallDialogView::~ExtensionInstallDialogView() {} |
| 550 | 629 |
| 551 void ExtensionInstallDialogView::SizeToContents() { | 630 void ExtensionInstallDialogView::ContentsChanged() { |
| 552 GetWidget()->SetSize(GetWidget()->non_client_view()->GetPreferredSize()); | 631 Layout(); |
| 553 } | 632 } |
| 554 | 633 |
| 555 int ExtensionInstallDialogView::GetDialogButtons() const { | 634 int ExtensionInstallDialogView::GetDialogButtons() const { |
| 556 int buttons = prompt_.GetDialogButtons(); | 635 int buttons = prompt_.GetDialogButtons(); |
| 557 // Simply having just an OK button is *not* supported. See comment on function | 636 // Simply having just an OK button is *not* supported. See comment on function |
| 558 // GetDialogButtons in dialog_delegate.h for reasons. | 637 // GetDialogButtons in dialog_delegate.h for reasons. |
| 559 DCHECK_GT(buttons & ui::DIALOG_BUTTON_CANCEL, 0); | 638 DCHECK_GT(buttons & ui::DIALOG_BUTTON_CANCEL, 0); |
| 560 return buttons; | 639 return buttons; |
| 561 } | 640 } |
| 562 | 641 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 601 int event_flags) { | 680 int event_flags) { |
| 602 GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() + | 681 GURL store_url(extension_urls::GetWebstoreItemDetailURLPrefix() + |
| 603 prompt_.extension()->id()); | 682 prompt_.extension()->id()); |
| 604 OpenURLParams params( | 683 OpenURLParams params( |
| 605 store_url, Referrer(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK, | 684 store_url, Referrer(), NEW_FOREGROUND_TAB, content::PAGE_TRANSITION_LINK, |
| 606 false); | 685 false); |
| 607 navigator_->OpenURL(params); | 686 navigator_->OpenURL(params); |
| 608 GetWidget()->Close(); | 687 GetWidget()->Close(); |
| 609 } | 688 } |
| 610 | 689 |
| 690 void ExtensionInstallDialogView::Layout() { | |
| 691 views::View* contents_view = scroll_view_->contents(); | |
| 692 int content_width = width(); | |
| 693 int content_height = contents_view->GetHeightForWidth(content_width); | |
| 694 if (content_height > height()) { | |
| 695 content_width -= scroll_view_->GetScrollBarWidth(); | |
| 696 content_height = contents_view->GetHeightForWidth(content_width); | |
| 697 } | |
| 698 contents_view->SetBounds(0, 0, content_width, content_height); | |
| 699 scroll_view_->SetBounds(0, 0, width(), height()); | |
| 700 | |
| 701 DialogDelegateView::Layout(); | |
| 702 } | |
| 703 | |
| 704 gfx::Size ExtensionInstallDialogView::GetPreferredSize() { | |
| 705 return dialog_size_; | |
| 706 } | |
| 707 | |
| 611 // static | 708 // static |
| 612 ExtensionInstallPrompt::ShowDialogCallback | 709 ExtensionInstallPrompt::ShowDialogCallback |
| 613 ExtensionInstallPrompt::GetDefaultShowDialogCallback() { | 710 ExtensionInstallPrompt::GetDefaultShowDialogCallback() { |
| 614 return base::Bind(&ShowExtensionInstallDialogImpl); | 711 return base::Bind(&ShowExtensionInstallDialogImpl); |
| 615 } | 712 } |
| 616 | 713 |
| 617 // IssueAdviceView::DetailsView ------------------------------------------------ | 714 // ExpandableContainerView::DetailsView ---------------------------------------- |
| 618 | 715 |
| 619 IssueAdviceView::DetailsView::DetailsView(int horizontal_space) | 716 ExpandableContainerView::DetailsView::DetailsView( |
| 717 int horizontal_space, bool show_bullets) | |
| 620 : layout_(new views::GridLayout(this)), | 718 : layout_(new views::GridLayout(this)), |
| 621 state_(0) { | 719 state_(0), |
| 720 show_bullets_(show_bullets) { | |
| 622 SetLayoutManager(layout_); | 721 SetLayoutManager(layout_); |
| 623 views::ColumnSet* column_set = layout_->AddColumnSet(0); | 722 views::ColumnSet* column_set = layout_->AddColumnSet(0); |
| 723 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); | |
| 624 column_set->AddColumn(views::GridLayout::LEADING, | 724 column_set->AddColumn(views::GridLayout::LEADING, |
| 625 views::GridLayout::LEADING, | 725 views::GridLayout::LEADING, |
| 626 0, | 726 0, |
| 627 views::GridLayout::FIXED, | 727 views::GridLayout::FIXED, |
| 628 horizontal_space, | 728 horizontal_space, |
| 629 0); | 729 0); |
| 630 } | 730 } |
| 631 | 731 |
| 632 void IssueAdviceView::DetailsView::AddDetail(const string16& detail) { | 732 void ExpandableContainerView::DetailsView::AddDetail(const string16& detail) { |
| 633 layout_->StartRowWithPadding(0, 0, | 733 layout_->StartRowWithPadding(0, 0, |
| 634 0, views::kRelatedControlSmallVerticalSpacing); | 734 0, views::kRelatedControlSmallVerticalSpacing); |
| 635 views::Label* detail_label = | 735 views::Label* detail_label = |
| 636 new views::Label(PrepareForDisplay(detail, true)); | 736 new views::Label(PrepareForDisplay(detail, show_bullets_)); |
| 637 detail_label->SetMultiLine(true); | 737 detail_label->SetMultiLine(true); |
| 638 detail_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | 738 detail_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 639 layout_->AddView(detail_label); | 739 layout_->AddView(detail_label); |
| 640 } | 740 } |
| 641 | 741 |
| 642 gfx::Size IssueAdviceView::DetailsView::GetPreferredSize() { | 742 gfx::Size ExpandableContainerView::DetailsView::GetPreferredSize() { |
| 643 gfx::Size size = views::View::GetPreferredSize(); | 743 gfx::Size size = views::View::GetPreferredSize(); |
| 644 return gfx::Size(size.width(), size.height() * state_); | 744 return gfx::Size(size.width(), size.height() * state_); |
| 645 } | 745 } |
| 646 | 746 |
| 647 void IssueAdviceView::DetailsView::AnimateToState(double state) { | 747 void ExpandableContainerView::DetailsView::AnimateToState(double state) { |
| 648 state_ = state; | 748 state_ = state; |
| 649 PreferredSizeChanged(); | 749 PreferredSizeChanged(); |
| 650 SchedulePaint(); | 750 SchedulePaint(); |
| 651 } | 751 } |
| 652 | 752 |
| 653 // IssueAdviceView ------------------------------------------------------------- | 753 // ExpandableContainerView ----------------------------------------------------- |
| 654 | 754 |
| 655 IssueAdviceView::IssueAdviceView(ExtensionInstallDialogView* owner, | 755 ExpandableContainerView::ExpandableContainerView( |
| 656 const IssueAdviceInfoEntry& issue_advice, | 756 ExtensionInstallDialogView* owner, |
| 657 int horizontal_space) | 757 const string16& description, |
| 758 const std::vector<string16>& details, | |
| 759 int horizontal_space, | |
| 760 bool show_bullets) | |
| 658 : owner_(owner), | 761 : owner_(owner), |
| 659 details_view_(NULL), | 762 details_view_(NULL), |
| 660 arrow_view_(NULL), | 763 arrow_view_(NULL), |
| 661 slide_animation_(this) { | 764 slide_animation_(this), |
| 662 // TODO(estade): replace this with a more appropriate image. | 765 expanded_(false) { |
| 663 const gfx::ImageSkia& image = *ui::ResourceBundle::GetSharedInstance(). | |
| 664 GetImageSkiaNamed(IDR_OMNIBOX_TTS); | |
| 665 | |
| 666 views::GridLayout* layout = new views::GridLayout(this); | 766 views::GridLayout* layout = new views::GridLayout(this); |
| 667 SetLayoutManager(layout); | 767 SetLayoutManager(layout); |
| 668 int column_set_id = 0; | 768 int column_set_id = 0; |
| 669 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); | 769 views::ColumnSet* column_set = layout->AddColumnSet(column_set_id); |
| 670 if (!issue_advice.details.empty()) { | |
| 671 column_set->AddColumn(views::GridLayout::LEADING, | |
| 672 views::GridLayout::LEADING, | |
| 673 0, | |
| 674 views::GridLayout::FIXED, | |
| 675 image.width(), | |
| 676 0); | |
| 677 horizontal_space -= image.width(); | |
| 678 details_view_ = new DetailsView(horizontal_space); | |
| 679 } | |
| 680 column_set->AddColumn(views::GridLayout::LEADING, | 770 column_set->AddColumn(views::GridLayout::LEADING, |
| 681 views::GridLayout::FILL, | 771 views::GridLayout::LEADING, |
| 682 0, | 772 0, |
| 683 views::GridLayout::FIXED, | 773 views::GridLayout::USE_PREF, |
| 684 horizontal_space, | 774 0, |
| 685 0); | 775 0); |
| 686 layout->StartRow(0, column_set_id); | 776 if (!description.empty()) { |
| 777 layout->StartRow(0, column_set_id); | |
| 687 | 778 |
| 688 if (details_view_) { | 779 views::Label* description_label = |
| 689 arrow_view_ = new views::ImageView(); | 780 new views::Label(PrepareForDisplay(description, true)); |
| 690 arrow_view_->SetImage(image); | 781 description_label->SetMultiLine(true); |
| 691 arrow_view_->SetVerticalAlignment(views::ImageView::CENTER); | 782 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
| 692 layout->AddView(arrow_view_); | 783 description_label->SizeToFit(horizontal_space); |
| 784 layout->AddView(description_label); | |
| 693 } | 785 } |
| 694 | 786 |
| 695 views::Label* description_label = | 787 if (details.empty()) |
| 696 new views::Label(PrepareForDisplay(issue_advice.description, | |
| 697 !details_view_)); | |
| 698 description_label->SetMultiLine(true); | |
| 699 description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 700 description_label->SizeToFit(horizontal_space); | |
| 701 layout->AddView(description_label); | |
| 702 | |
| 703 if (!details_view_) | |
| 704 return; | 788 return; |
| 705 | 789 |
| 790 details_view_ = new DetailsView(horizontal_space, show_bullets); | |
| 791 | |
| 706 layout->StartRow(0, column_set_id); | 792 layout->StartRow(0, column_set_id); |
| 707 layout->SkipColumns(1); | |
| 708 layout->AddView(details_view_); | 793 layout->AddView(details_view_); |
| 709 | 794 |
| 710 for (size_t i = 0; i < issue_advice.details.size(); ++i) | 795 for (size_t i = 0; i < details.size(); ++i) |
| 711 details_view_->AddDetail(issue_advice.details[i]); | 796 details_view_->AddDetail(details[i]); |
| 797 | |
| 798 // Prepare the columns for the More Details row. | |
| 799 column_set = layout->AddColumnSet(++column_set_id); | |
| 800 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); | |
| 801 column_set->AddColumn(views::GridLayout::LEADING, | |
| 802 views::GridLayout::LEADING, | |
| 803 0, | |
| 804 views::GridLayout::USE_PREF, | |
| 805 0, | |
| 806 0); | |
| 807 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); | |
| 808 column_set->AddColumn(views::GridLayout::LEADING, | |
| 809 views::GridLayout::LEADING, | |
| 810 0, | |
| 811 views::GridLayout::USE_PREF, | |
| 812 0, | |
| 813 0); | |
| 814 column_set->AddColumn(views::GridLayout::LEADING, | |
| 815 views::GridLayout::LEADING, | |
| 816 0, | |
| 817 views::GridLayout::USE_PREF, | |
| 818 0, | |
| 819 0); | |
| 820 | |
| 821 // Add the More Details link. | |
| 822 layout->StartRow(0, column_set_id); | |
| 823 more_details_ = new views::Link( | |
| 824 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS)); | |
| 825 more_details_->set_listener(this); | |
| 826 more_details_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
| 827 layout->AddView(more_details_); | |
| 828 | |
| 829 // Add the arrow after the More Details link. | |
| 830 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 831 arrow_toggle_ = new views::ImageButton(this); | |
| 832 arrow_toggle_->SetImage(views::Button::STATE_NORMAL, | |
| 833 rb.GetImageSkiaNamed(IDR_DOWN_ARROW)); | |
| 834 layout->AddView(arrow_toggle_); | |
| 712 } | 835 } |
| 713 | 836 |
| 714 bool IssueAdviceView::OnMousePressed(const ui::MouseEvent& event) { | 837 void ExpandableContainerView::ButtonPressed( |
| 715 return details_view_ && event.IsLeftMouseButton(); | 838 views::Button* sender, const ui::Event& event) { |
| 839 ToggleDetailLevel(); | |
| 716 } | 840 } |
| 717 | 841 |
| 718 void IssueAdviceView::OnMouseReleased(const ui::MouseEvent& event) { | 842 void ExpandableContainerView::LinkClicked( |
| 843 views::Link* source, int event_flags) { | |
| 844 ToggleDetailLevel(); | |
| 845 } | |
| 846 | |
| 847 void ExpandableContainerView::AnimationProgressed( | |
| 848 const ui::Animation* animation) { | |
| 849 DCHECK_EQ(animation, &slide_animation_); | |
| 850 | |
| 851 if (details_view_) | |
| 852 details_view_->AnimateToState(animation->GetCurrentValue()); | |
| 853 } | |
| 854 | |
| 855 void ExpandableContainerView::AnimationEnded(const ui::Animation* animation) { | |
| 856 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 857 if (animation->GetCurrentValue() != 0.0) { | |
| 858 arrow_toggle_->SetImage(views::Button::STATE_NORMAL, | |
| 859 rb.GetImageSkiaNamed(IDR_UP_ARROW)); | |
| 860 } else { | |
| 861 arrow_toggle_->SetImage(views::Button::STATE_NORMAL, | |
| 862 rb.GetImageSkiaNamed(IDR_DOWN_ARROW)); | |
| 863 } | |
| 864 | |
| 865 more_details_->SetText( | |
| 866 expanded_ ? l10n_util::GetStringUTF16(IDS_EXTENSIONS_HIDE_DETAILS) : | |
| 867 l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_DETAILS)); | |
| 868 } | |
| 869 | |
| 870 void ExpandableContainerView::ChildPreferredSizeChanged(views::View* child) { | |
| 871 owner_->ContentsChanged(); | |
| 872 } | |
| 873 | |
| 874 void ExpandableContainerView::ToggleDetailLevel() { | |
| 875 expanded_ = !expanded_; | |
| 876 | |
| 719 if (slide_animation_.IsShowing()) | 877 if (slide_animation_.IsShowing()) |
| 720 slide_animation_.Hide(); | 878 slide_animation_.Hide(); |
| 721 else | 879 else |
| 722 slide_animation_.Show(); | 880 slide_animation_.Show(); |
| 723 } | 881 } |
| 724 | |
| 725 void IssueAdviceView::AnimationProgressed(const ui::Animation* animation) { | |
| 726 DCHECK_EQ(animation, &slide_animation_); | |
| 727 | |
| 728 if (details_view_) | |
| 729 details_view_->AnimateToState(animation->GetCurrentValue()); | |
| 730 | |
| 731 if (arrow_view_) { | |
| 732 gfx::Transform rotate; | |
| 733 if (animation->GetCurrentValue() != 0.0) { | |
| 734 rotate.Translate(arrow_view_->width() / 2.0, | |
| 735 arrow_view_->height() / 2.0); | |
| 736 // TODO(estade): for some reason there are rendering errors at 90 degrees. | |
| 737 // Figure out why. | |
| 738 rotate.Rotate(animation->GetCurrentValue() * 89); | |
| 739 rotate.Translate(-arrow_view_->width() / 2.0, | |
| 740 -arrow_view_->height() / 2.0); | |
| 741 } | |
| 742 arrow_view_->SetTransform(rotate); | |
| 743 } | |
| 744 } | |
| 745 | |
| 746 void IssueAdviceView::ChildPreferredSizeChanged(views::View* child) { | |
| 747 owner_->SizeToContents(); | |
| 748 } | |
| OLD | NEW |