blob: f192c05fb88a5e2a4b5198a9112162dbc454a243 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/macros.h"
#include "chrome/browser/extensions/bundle_installer.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/toolbar/app_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_constants.h"
using extensions::BundleInstaller;
using views::GridLayout;
namespace {
// The ID of the column set that holds the headings and the close button.
const int kHeadingColumnSetId = 0;
// The width of the columns that hold the heading texts and extension names.
const int kTextColumnWidth = 325;
// The ID of the column set that holds extension icons and names.
const int kItemsColumnSetId = 1;
// The size of extension icons, and width of the corresponding column.
const int kIconSize = 32;
class BundleInstalledBubble : public views::BubbleDelegateView,
public views::ButtonListener {
public:
BundleInstalledBubble(const BundleInstaller* bundle,
View* anchor_view,
views::BubbleBorder::Arrow arrow)
: views::BubbleDelegateView(anchor_view, arrow) {
GridLayout* layout = GridLayout::CreatePanel(this);
SetLayoutManager(layout);
views::ColumnSet* heading_column_set =
layout->AddColumnSet(kHeadingColumnSetId);
heading_column_set->AddColumn(GridLayout::LEADING,
GridLayout::FILL,
100.0f, // take all available space
GridLayout::USE_PREF,
0, // no fixed width
kTextColumnWidth);
heading_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
heading_column_set->AddColumn(GridLayout::TRAILING,
GridLayout::LEADING,
0, // no resizing
GridLayout::USE_PREF,
0, // no fixed width
0); // no min width (only holds close button)
views::ColumnSet* items_column_set =
layout->AddColumnSet(kItemsColumnSetId);
items_column_set->AddColumn(GridLayout::CENTER,
GridLayout::CENTER,
0, // no resizing
GridLayout::FIXED,
kIconSize,
kIconSize);
items_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
items_column_set->AddColumn(GridLayout::LEADING,
GridLayout::CENTER,
100.0f, // take all available space
GridLayout::USE_PREF,
0, // no fixed width
kTextColumnWidth);
AddContent(layout, bundle);
}
~BundleInstalledBubble() override {}
private:
void AddContent(GridLayout* layout, const BundleInstaller* bundle) {
bool has_installed_items = bundle->HasItemWithState(
BundleInstaller::Item::STATE_INSTALLED);
bool has_failed_items = bundle->HasItemWithState(
BundleInstaller::Item::STATE_FAILED);
// Insert the list of installed items.
if (has_installed_items) {
layout->StartRow(0, kHeadingColumnSetId);
AddHeading(layout, bundle->GetHeadingTextFor(
BundleInstaller::Item::STATE_INSTALLED));
AddCloseButton(layout, this);
AddItemList(layout, bundle->GetItemsWithState(
BundleInstaller::Item::STATE_INSTALLED));
// Insert a line of padding if we're showing both sections.
if (has_failed_items)
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
}
// Insert the list of failed items.
if (has_failed_items) {
layout->StartRow(0, kHeadingColumnSetId);
AddHeading(layout, bundle->GetHeadingTextFor(
BundleInstaller::Item::STATE_FAILED));
// The close button should be in the second column of the first row, so
// we add it here if there was no installed items section.
if (!has_installed_items)
AddCloseButton(layout, this);
AddItemList(layout, bundle->GetItemsWithState(
BundleInstaller::Item::STATE_FAILED));
}
views::BubbleDelegateView::CreateBubble(this)->Show();
}
void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) {
for (const BundleInstaller::Item& item : items) {
layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
layout->StartRow(0, kItemsColumnSetId);
gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(item.icon);
gfx::Size size(image.width(), image.height());
if (size.width() > kIconSize || size.height() > kIconSize)
size = gfx::Size(kIconSize, kIconSize);
views::ImageView* image_view = new views::ImageView;
image_view->SetImage(image);
image_view->SetImageSize(size);
layout->AddView(image_view);
views::Label* extension_label =
new views::Label(item.GetNameForDisplay());
extension_label->SetMultiLine(true);
extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
extension_label->SizeToFit(kTextColumnWidth);
layout->AddView(extension_label);
}
}
void AddCloseButton(GridLayout* layout, views::ButtonListener* listener) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
views::ImageButton* button = new views::ImageButton(listener);
button->SetImage(views::CustomButton::STATE_NORMAL,
rb.GetImageSkiaNamed(IDR_CLOSE_2));
button->SetImage(views::CustomButton::STATE_HOVERED,
rb.GetImageSkiaNamed(IDR_CLOSE_2_H));
button->SetImage(views::CustomButton::STATE_PRESSED,
rb.GetImageSkiaNamed(IDR_CLOSE_2_P));
layout->AddView(button);
}
void AddHeading(GridLayout* layout, const base::string16& heading) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
views::Label* heading_label = new views::Label(
heading, rb.GetFontList(ui::ResourceBundle::MediumFont));
heading_label->SetMultiLine(true);
heading_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
heading_label->SizeToFit(kTextColumnWidth);
layout->AddView(heading_label);
}
// views::ButtonListener implementation:
void ButtonPressed(views::Button* sender, const ui::Event& event) override {
GetWidget()->Close();
}
DISALLOW_COPY_AND_ASSIGN(BundleInstalledBubble);
};
} // namespace
void BundleInstaller::ShowInstalledBubble(
const BundleInstaller* bundle, Browser* browser) {
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
views::View* anchor = browser_view->GetToolbarView()->app_menu_button();
new BundleInstalledBubble(bundle, anchor, views::BubbleBorder::TOP_RIGHT);
}