Index: chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc |
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc |
index ec1c04cb7401a986bd63d32fbb5143411fbb182d..2abd0c7c87ac0d526612d47903821312751c36f4 100644 |
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc |
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc |
@@ -44,6 +44,222 @@ |
// Size of extension icon in top left of dialog. |
const int kIconSize = 64; |
+namespace { |
+ |
+// A small summary panel with the app's name, icon, version, and a link to the |
+// web store (if they exist). |
+class AppInfoSummaryPanel : public views::View, |
+ public views::LinkListener, |
+ public base::SupportsWeakPtr<AppInfoSummaryPanel> { |
+ public: |
+ AppInfoSummaryPanel(Profile* profile, const extensions::Extension* app); |
+ virtual ~AppInfoSummaryPanel(); |
+ |
+ private: |
+ void CreateControls(); |
+ void LayoutAppNameAndVersionInto(views::View* parent_view); |
+ void LayoutViews(); |
+ |
+ // Overridden from views::LinkListener: |
+ virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE; |
+ |
+ // Load the app icon asynchronously. For the response, check OnAppImageLoaded. |
+ void LoadAppImageAsync(); |
+ // Called when the app's icon is loaded. |
+ void OnAppImageLoaded(const gfx::Image& image); |
+ |
+ // Opens the app in the web store. Must only be called if |
+ // CanShowAppInWebStore() returns true. |
+ void ShowAppInWebStore() const; |
+ bool CanShowAppInWebStore() const; |
+ |
+ views::ImageView* app_icon_; |
+ views::Label* app_name_label_; |
+ views::Label* app_version_label_; |
+ views::Link* view_in_store_link_; |
+ |
+ Profile* profile_; |
+ const extensions::Extension* app_; |
benwells
2014/05/19 22:21:37
Hmmm .... can you file a bug on yourself to make y
|
+ |
+ base::WeakPtrFactory<AppInfoSummaryPanel> weak_ptr_factory_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(AppInfoSummaryPanel); |
+}; |
+ |
+AppInfoSummaryPanel::AppInfoSummaryPanel(Profile* profile, |
+ const extensions::Extension* app) |
+ : app_icon_(NULL), |
+ app_name_label_(NULL), |
+ app_version_label_(NULL), |
+ view_in_store_link_(NULL), |
+ profile_(profile), |
+ app_(app), |
+ weak_ptr_factory_(this) { |
+ CreateControls(); |
+ |
+ // Layout elements. |
+ SetLayoutManager( |
+ new views::BoxLayout(views::BoxLayout::kHorizontal, |
+ 0, |
+ 0, |
+ views::kRelatedControlHorizontalSpacing)); |
+ |
+ AddChildView(app_icon_); |
+ |
+ if (!app_version_label_ && !view_in_store_link_) { |
+ // If there's no link to the webstore _and_ no version, allow the app's name |
+ // to take up multiple lines. |
+ app_name_label_->SetMultiLine(true); |
+ AddChildView(app_name_label_); |
+ } else { |
+ // Create a vertical container to store the app's name and info. |
+ views::View* vertical_container = new views::View(); |
+ views::BoxLayout* vertical_container_layout = |
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); |
+ vertical_container_layout->set_main_axis_alignment( |
+ views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); |
+ vertical_container->SetLayoutManager(vertical_container_layout); |
+ |
+ if (app_version_label_ && view_in_store_link_) { |
+ // First line: title and version, Second line: web store link. |
+ LayoutAppNameAndVersionInto(vertical_container); |
+ vertical_container->AddChildView(view_in_store_link_); |
+ } else { |
+ // Put the title on the first line, and whatever other information we have |
+ // on the second line. |
+ vertical_container->AddChildView(app_name_label_); |
+ |
+ if (app_version_label_) { |
+ vertical_container->AddChildView(app_version_label_); |
+ } else if (view_in_store_link_) { |
+ vertical_container->AddChildView(view_in_store_link_); |
+ } |
+ } |
+ |
+ AddChildView(vertical_container); |
+ } |
+} |
+ |
+AppInfoSummaryPanel::~AppInfoSummaryPanel() { |
+} |
+ |
+void AppInfoSummaryPanel::CreateControls() { |
+ app_name_label_ = |
+ new views::Label(base::UTF8ToUTF16(app_->name()), |
+ ui::ResourceBundle::GetSharedInstance().GetFontList( |
+ ui::ResourceBundle::BoldFont)); |
+ app_name_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
+ |
+ // The version number doesn't make sense for bookmarked apps. |
+ if (!app_->from_bookmark()) { |
+ app_version_label_ = |
+ new views::Label(base::UTF8ToUTF16(app_->VersionString())); |
+ app_version_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
+ } |
+ |
+ app_icon_ = new views::ImageView(); |
+ app_icon_->SetImageSize(gfx::Size(kIconSize, kIconSize)); |
+ LoadAppImageAsync(); |
+ |
+ if (CanShowAppInWebStore()) { |
+ view_in_store_link_ = new views::Link( |
+ l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK)); |
+ view_in_store_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
+ view_in_store_link_->set_listener(this); |
+ } |
+} |
+ |
+void AppInfoSummaryPanel::LayoutAppNameAndVersionInto( |
+ views::View* parent_view) { |
+ views::View* view = new views::View(); |
+ // We need a horizontal BoxLayout here to ensure that the GridLayout does |
+ // not stretch beyond the size of its content. |
+ view->SetLayoutManager( |
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); |
+ |
+ views::View* container_view = new views::View(); |
+ view->AddChildView(container_view); |
+ views::GridLayout* layout = new views::GridLayout(container_view); |
+ container_view->SetLayoutManager(layout); |
+ |
+ static const int kColumnId = 1; |
+ views::ColumnSet* column_set = layout->AddColumnSet(kColumnId); |
+ column_set->AddColumn(views::GridLayout::LEADING, |
+ views::GridLayout::LEADING, |
+ 1, // Stretch the title to as wide as needed |
+ views::GridLayout::USE_PREF, |
+ 0, |
+ 0); |
+ column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing); |
+ column_set->AddColumn(views::GridLayout::LEADING, |
+ views::GridLayout::LEADING, |
+ 0, // Do not stretch the version |
+ views::GridLayout::USE_PREF, |
+ 0, |
+ 0); |
+ |
+ layout->StartRow(1, kColumnId); |
+ layout->AddView(app_name_label_); |
+ if (app_version_label_) |
+ layout->AddView(app_version_label_); |
+ |
+ parent_view->AddChildView(view); |
+} |
+ |
+void AppInfoSummaryPanel::LinkClicked(views::Link* source, int event_flags) { |
+ if (source == view_in_store_link_) { |
+ ShowAppInWebStore(); |
+ } else { |
+ NOTREACHED(); |
+ } |
+} |
+ |
+void AppInfoSummaryPanel::LoadAppImageAsync() { |
+ extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource( |
+ app_, |
+ extension_misc::EXTENSION_ICON_LARGE, |
+ ExtensionIconSet::MATCH_BIGGER); |
+ int pixel_size = |
+ static_cast<int>(kIconSize * gfx::ImageSkia::GetMaxSupportedScale()); |
+ extensions::ImageLoader::Get(profile_)->LoadImageAsync( |
+ app_, |
+ image, |
+ gfx::Size(pixel_size, pixel_size), |
+ base::Bind(&AppInfoSummaryPanel::OnAppImageLoaded, AsWeakPtr())); |
+} |
+ |
+void AppInfoSummaryPanel::OnAppImageLoaded(const gfx::Image& image) { |
+ const SkBitmap* bitmap; |
+ if (image.IsEmpty()) { |
+ bitmap = &extensions::util::GetDefaultAppIcon() |
+ .GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale()) |
+ .sk_bitmap(); |
+ } else { |
+ bitmap = image.ToSkBitmap(); |
+ } |
+ |
+ app_icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap)); |
+} |
+ |
+void AppInfoSummaryPanel::ShowAppInWebStore() const { |
+ DCHECK(CanShowAppInWebStore()); |
+ const GURL url = extensions::ManifestURL::GetDetailsURL(app_); |
+ DCHECK_NE(url, GURL::EmptyGURL()); |
+ chrome::NavigateParams params( |
+ profile_, |
+ net::AppendQueryParameter(url, |
+ extension_urls::kWebstoreSourceField, |
+ extension_urls::kLaunchSourceAppListInfoDialog), |
+ content::PAGE_TRANSITION_LINK); |
+ chrome::Navigate(¶ms); |
+} |
+ |
+bool AppInfoSummaryPanel::CanShowAppInWebStore() const { |
+ return app_->from_webstore(); |
+} |
+ |
+} // namespace |
+ |
// A model for a combobox selecting the launch options for a hosted app. |
// Displays different options depending on the host OS. |
class LaunchOptionsComboboxModel : public ui::ComboboxModel { |
@@ -131,105 +347,52 @@ int LaunchOptionsComboboxModel::GetIndexForLaunchType( |
int LaunchOptionsComboboxModel::GetItemCount() const { |
return launch_types_.size(); |
-}; |
+} |
base::string16 LaunchOptionsComboboxModel::GetItemAt(int index) { |
return launch_type_messages_[index]; |
-}; |
+} |
AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window, |
Profile* profile, |
const extensions::Extension* app, |
const base::Closure& close_callback) |
: AppInfoTab(parent_window, profile, app, close_callback), |
- app_icon_(NULL), |
- view_in_store_link_(NULL), |
+ app_summary_panel_(NULL), |
+ app_description_label_(NULL), |
create_shortcuts_button_(NULL), |
uninstall_button_(NULL), |
- launch_options_combobox_(NULL), |
- weak_ptr_factory_(this) { |
+ launch_options_combobox_(NULL) { |
// Create UI elements. |
- views::Label* app_name_label = |
- new views::Label(base::UTF8ToUTF16(app_->name()), |
- ui::ResourceBundle::GetSharedInstance().GetFontList( |
- ui::ResourceBundle::BoldFont)); |
- app_name_label->SetMultiLine(true); |
- app_name_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- |
- app_icon_ = new views::ImageView(); |
- app_icon_->SetImageSize(gfx::Size(kIconSize, kIconSize)); |
- LoadAppImageAsync(); |
+ app_summary_panel_ = new AppInfoSummaryPanel(profile_, app_); |
+ CreateDescriptionControl(); |
+ CreateLaunchOptionControl(); |
+ CreateButtons(); |
- // Create the layout. |
- views::GridLayout* layout = views::GridLayout::CreatePanel(this); |
- SetLayoutManager(layout); |
- |
- // Create a Header column set with app icon and information. |
- static const int kHeaderColumnSetId = 0; |
- views::ColumnSet* header_column_set = |
- layout->AddColumnSet(kHeaderColumnSetId); |
- header_column_set->AddColumn(views::GridLayout::FILL, |
- views::GridLayout::CENTER, |
- 0, |
- views::GridLayout::FIXED, |
- kIconSize, |
- 0); |
- header_column_set->AddPaddingColumn(0, |
- views::kRelatedControlHorizontalSpacing); |
- header_column_set->AddColumn(views::GridLayout::FILL, |
- views::GridLayout::CENTER, |
- 100.0f, |
- views::GridLayout::FIXED, |
- 0, |
- 0); |
- |
- // Create a main column set for the rest of the dialog content. |
- static const int kMainColumnSetId = 1; |
- views::ColumnSet* main_column_set = layout->AddColumnSet(kMainColumnSetId); |
- main_column_set->AddColumn(views::GridLayout::FILL, |
- views::GridLayout::LEADING, |
- 100.0f, |
- views::GridLayout::FIXED, |
- 0, |
- 0); |
- |
- // To vertically align the app's information to the center of the icon, we |
- // need to place the info in its own view. This view can then be vertically |
- // centered in its column. |
- views::View* appInfoTextContainer = new views::View(); |
- appInfoTextContainer->SetLayoutManager( |
+ // Layout elements. |
+ SetLayoutManager( |
new views::BoxLayout(views::BoxLayout::kVertical, |
- 0, |
- 0, |
- views::kRelatedControlSmallVerticalSpacing)); |
+ views::kButtonHEdgeMarginNew, |
+ views::kPanelVertMargin, |
+ views::kUnrelatedControlVerticalSpacing)); |
- // All apps have a name. |
- appInfoTextContainer->AddChildView(app_name_label); |
+ AddChildView(app_summary_panel_); |
- // The version number doesn't make sense for bookmarked apps. |
- if (!app_->from_bookmark()) { |
- views::Label* app_version_label = |
- new views::Label(base::UTF8ToUTF16(app_->VersionString())); |
- app_version_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
+ if (app_description_label_) |
+ AddChildView(app_description_label_); |
- appInfoTextContainer->AddChildView(app_version_label); |
- } |
+ if (launch_options_combobox_) |
+ AddChildView(launch_options_combobox_); |
- // Add a link to the web store for apps that have it. |
- if (CanShowAppInWebStore()) { |
- view_in_store_link_ = new views::Link( |
- l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_WEB_STORE_LINK)); |
- view_in_store_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- view_in_store_link_->set_listener(this); |
- |
- appInfoTextContainer->AddChildView(view_in_store_link_); |
- } |
+ LayoutButtons(); |
+} |
- layout->StartRow(0, kHeaderColumnSetId); |
- layout->AddView(app_icon_); |
- layout->AddView(appInfoTextContainer); |
+AppInfoSummaryTab::~AppInfoSummaryTab() { |
+ // Destroy view children before their models. |
+ RemoveAllChildViews(true); |
+} |
- // Add the description, if the app has one. |
+void AppInfoSummaryTab::CreateDescriptionControl() { |
if (!app_->description().empty()) { |
const size_t kMaxLength = 400; |
@@ -239,16 +402,13 @@ AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window, |
text += base::ASCIIToUTF16(" ... "); |
} |
- views::Label* app_description_label = new views::Label(text); |
- app_description_label->SetMultiLine(true); |
- app_description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
- |
- layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); |
- layout->StartRow(0, kMainColumnSetId); |
- layout->AddView(app_description_label); |
+ app_description_label_ = new views::Label(text); |
+ app_description_label_->SetMultiLine(true); |
+ app_description_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
} |
+} |
- // Add hosted app launch options for non-platform apps. |
+void AppInfoSummaryTab::CreateLaunchOptionControl() { |
if (CanSetLaunchType()) { |
launch_options_combobox_model_.reset(new LaunchOptionsComboboxModel()); |
launch_options_combobox_ = |
@@ -257,69 +417,41 @@ AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window, |
launch_options_combobox_->set_listener(this); |
launch_options_combobox_->SetSelectedIndex( |
launch_options_combobox_model_->GetIndexForLaunchType(GetLaunchType())); |
- |
- layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); |
- layout->StartRow(0, kMainColumnSetId); |
- layout->AddView(launch_options_combobox_); |
} |
+} |
- if (CanCreateShortcuts() || CanUninstallApp()) { |
- // Create a column set specifically for the left-aligned buttons at the |
- // bottom of the dialog. |
- static const int kButtonsColumnSetId = 2; |
- views::ColumnSet* buttons_column_set = |
- layout->AddColumnSet(kButtonsColumnSetId); |
- buttons_column_set->AddColumn(views::GridLayout::LEADING, |
- views::GridLayout::LEADING, |
- 0, |
- views::GridLayout::USE_PREF, |
- 0, // No fixed width |
- 0); |
- buttons_column_set->AddPaddingColumn( |
- 0, views::kRelatedControlHorizontalSpacing); |
- buttons_column_set->AddColumn(views::GridLayout::LEADING, |
- views::GridLayout::LEADING, |
- 0, |
- views::GridLayout::USE_PREF, |
- 0, // No fixed width |
- 0); |
- |
- layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing); |
- layout->StartRow(0, kButtonsColumnSetId); |
- |
- // Add a Create Shortcuts button for apps that can have shortcuts. |
- if (CanCreateShortcuts()) { |
- create_shortcuts_button_ = new views::LabelButton( |
- this, |
- l10n_util::GetStringUTF16( |
- IDS_APPLICATION_INFO_CREATE_SHORTCUTS_BUTTON_TEXT)); |
- create_shortcuts_button_->SetStyle(views::Button::STYLE_BUTTON); |
- layout->AddView(create_shortcuts_button_); |
- } |
+void AppInfoSummaryTab::CreateButtons() { |
+ if (CanCreateShortcuts()) { |
+ create_shortcuts_button_ = new views::LabelButton( |
+ this, |
+ l10n_util::GetStringUTF16( |
+ IDS_APPLICATION_INFO_CREATE_SHORTCUTS_BUTTON_TEXT)); |
+ create_shortcuts_button_->SetStyle(views::Button::STYLE_BUTTON); |
+ } |
- // Add an uninstall button for apps that can be uninstalled. |
- if (CanUninstallApp()) { |
- uninstall_button_ = new views::LabelButton( |
- this, |
- l10n_util::GetStringUTF16( |
- IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT)); |
- uninstall_button_->SetStyle(views::Button::STYLE_BUTTON); |
- layout->AddView(uninstall_button_); |
- } |
+ if (CanUninstallApp()) { |
+ uninstall_button_ = new views::LabelButton( |
+ this, |
+ l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_UNINSTALL_BUTTON_TEXT)); |
+ uninstall_button_->SetStyle(views::Button::STYLE_BUTTON); |
} |
} |
-AppInfoSummaryTab::~AppInfoSummaryTab() { |
- // Destroy view children before their models. |
- RemoveAllChildViews(true); |
-} |
+void AppInfoSummaryTab::LayoutButtons() { |
+ views::View* app_buttons = new views::View(); |
+ app_buttons->SetLayoutManager( |
+ new views::BoxLayout(views::BoxLayout::kHorizontal, |
+ 0, |
+ 0, |
+ views::kRelatedControlVerticalSpacing)); |
-void AppInfoSummaryTab::LinkClicked(views::Link* source, int event_flags) { |
- if (source == view_in_store_link_) { |
- ShowAppInWebStore(); |
- } else { |
- NOTREACHED(); |
- } |
+ if (create_shortcuts_button_) |
+ app_buttons->AddChildView(create_shortcuts_button_); |
+ |
+ if (uninstall_button_) |
+ app_buttons->AddChildView(uninstall_button_); |
+ |
+ AddChildView(app_buttons); |
} |
void AppInfoSummaryTab::OnPerformAction(views::Combobox* combobox) { |
@@ -355,33 +487,6 @@ void AppInfoSummaryTab::ExtensionUninstallCanceled() { |
extension_uninstall_dialog_.reset(); |
} |
-void AppInfoSummaryTab::LoadAppImageAsync() { |
- extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource( |
- app_, |
- extension_misc::EXTENSION_ICON_LARGE, |
- ExtensionIconSet::MATCH_BIGGER); |
- int pixel_size = |
- static_cast<int>(kIconSize * gfx::ImageSkia::GetMaxSupportedScale()); |
- extensions::ImageLoader::Get(profile_)->LoadImageAsync( |
- app_, |
- image, |
- gfx::Size(pixel_size, pixel_size), |
- base::Bind(&AppInfoSummaryTab::OnAppImageLoaded, AsWeakPtr())); |
-} |
- |
-void AppInfoSummaryTab::OnAppImageLoaded(const gfx::Image& image) { |
- const SkBitmap* bitmap; |
- if (image.IsEmpty()) { |
- bitmap = &extensions::util::GetDefaultAppIcon() |
- .GetRepresentation(gfx::ImageSkia::GetMaxSupportedScale()) |
- .sk_bitmap(); |
- } else { |
- bitmap = image.ToSkBitmap(); |
- } |
- |
- app_icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap)); |
-} |
- |
extensions::LaunchType AppInfoSummaryTab::GetLaunchType() const { |
return extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile_), |
app_); |
@@ -400,23 +505,6 @@ bool AppInfoSummaryTab::CanSetLaunchType() const { |
return !app_->is_platform_app(); |
} |
-void AppInfoSummaryTab::ShowAppInWebStore() const { |
- DCHECK(CanShowAppInWebStore()); |
- const GURL url = extensions::ManifestURL::GetDetailsURL(app_); |
- DCHECK_NE(url, GURL::EmptyGURL()); |
- chrome::NavigateParams params( |
- profile_, |
- net::AppendQueryParameter(url, |
- extension_urls::kWebstoreSourceField, |
- extension_urls::kLaunchSourceAppListInfoDialog), |
- content::PAGE_TRANSITION_LINK); |
- chrome::Navigate(¶ms); |
-} |
- |
-bool AppInfoSummaryTab::CanShowAppInWebStore() const { |
- return app_->from_webstore(); |
-} |
- |
void AppInfoSummaryTab::UninstallApp() { |
DCHECK(CanUninstallApp()); |
extension_uninstall_dialog_.reset( |