Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / extensions / bundle_installed_bubble.cc
blob5ef269b9a6e71f433822ccef947d4c14138e978a
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/bundle_installer.h"
6 #include "chrome/browser/ui/browser.h"
7 #include "chrome/browser/ui/views/frame/browser_view.h"
8 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
9 #include "chrome/browser/ui/views/toolbar/wrench_toolbar_button.h"
10 #include "ui/base/resource/resource_bundle.h"
11 #include "ui/resources/grit/ui_resources.h"
12 #include "ui/views/bubble/bubble_delegate.h"
13 #include "ui/views/controls/button/image_button.h"
14 #include "ui/views/controls/label.h"
15 #include "ui/views/layout/grid_layout.h"
16 #include "ui/views/layout/layout_constants.h"
18 using extensions::BundleInstaller;
19 using views::GridLayout;
21 namespace {
23 // The ID of the column set that holds the headings and the close button.
24 const int kHeadingColumnSetId = 0;
26 // The width of the columns that hold the heading texts and extension names.
27 const int kTextColumnWidth = 325;
29 // The ID of the column set that holds extension icons and names.
30 const int kItemsColumnSetId = 1;
32 // The size of extension icons, and width of the corresponding column.
33 const int kIconSize = 32;
35 class BundleInstalledBubble : public views::BubbleDelegateView,
36 public views::ButtonListener {
37 public:
38 BundleInstalledBubble(const BundleInstaller* bundle,
39 View* anchor_view,
40 views::BubbleBorder::Arrow arrow)
41 : views::BubbleDelegateView(anchor_view, arrow) {
42 GridLayout* layout = GridLayout::CreatePanel(this);
43 SetLayoutManager(layout);
45 views::ColumnSet* heading_column_set =
46 layout->AddColumnSet(kHeadingColumnSetId);
47 heading_column_set->AddColumn(GridLayout::LEADING,
48 GridLayout::FILL,
49 100.0f, // take all available space
50 GridLayout::USE_PREF,
51 0, // no fixed width
52 kTextColumnWidth);
53 heading_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
54 heading_column_set->AddColumn(GridLayout::TRAILING,
55 GridLayout::LEADING,
56 0, // no resizing
57 GridLayout::USE_PREF,
58 0, // no fixed width
59 0); // no min width (only holds close button)
61 views::ColumnSet* items_column_set =
62 layout->AddColumnSet(kItemsColumnSetId);
63 items_column_set->AddColumn(GridLayout::CENTER,
64 GridLayout::CENTER,
65 0, // no resizing
66 GridLayout::FIXED,
67 kIconSize,
68 kIconSize);
69 items_column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
70 items_column_set->AddColumn(GridLayout::LEADING,
71 GridLayout::CENTER,
72 100.0f, // take all available space
73 GridLayout::USE_PREF,
74 0, // no fixed width
75 kTextColumnWidth);
77 AddContent(layout, bundle);
80 ~BundleInstalledBubble() override {}
82 private:
83 void AddContent(GridLayout* layout, const BundleInstaller* bundle) {
84 bool has_installed_items = bundle->HasItemWithState(
85 BundleInstaller::Item::STATE_INSTALLED);
86 bool has_failed_items = bundle->HasItemWithState(
87 BundleInstaller::Item::STATE_FAILED);
89 // Insert the list of installed items.
90 if (has_installed_items) {
91 layout->StartRow(0, kHeadingColumnSetId);
92 AddHeading(layout, bundle->GetHeadingTextFor(
93 BundleInstaller::Item::STATE_INSTALLED));
94 AddCloseButton(layout, this);
95 AddItemList(layout, bundle->GetItemsWithState(
96 BundleInstaller::Item::STATE_INSTALLED));
98 // Insert a line of padding if we're showing both sections.
99 if (has_failed_items)
100 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
103 // Insert the list of failed items.
104 if (has_failed_items) {
105 layout->StartRow(0, kHeadingColumnSetId);
106 AddHeading(layout, bundle->GetHeadingTextFor(
107 BundleInstaller::Item::STATE_FAILED));
109 // The close button should be in the second column of the first row, so
110 // we add it here if there was no installed items section.
111 if (!has_installed_items)
112 AddCloseButton(layout, this);
114 AddItemList(layout, bundle->GetItemsWithState(
115 BundleInstaller::Item::STATE_FAILED));
118 views::BubbleDelegateView::CreateBubble(this)->Show();
121 void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) {
122 for (const BundleInstaller::Item& item : items) {
123 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
124 layout->StartRow(0, kItemsColumnSetId);
125 gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(item.icon);
126 gfx::Size size(image.width(), image.height());
127 if (size.width() > kIconSize || size.height() > kIconSize)
128 size = gfx::Size(kIconSize, kIconSize);
129 views::ImageView* image_view = new views::ImageView;
130 image_view->SetImage(image);
131 image_view->SetImageSize(size);
132 layout->AddView(image_view);
134 views::Label* extension_label =
135 new views::Label(item.GetNameForDisplay());
136 extension_label->SetMultiLine(true);
137 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
138 extension_label->SizeToFit(kTextColumnWidth);
139 layout->AddView(extension_label);
143 void AddCloseButton(GridLayout* layout, views::ButtonListener* listener) {
144 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
146 views::ImageButton* button = new views::ImageButton(listener);
147 button->SetImage(views::CustomButton::STATE_NORMAL,
148 rb.GetImageSkiaNamed(IDR_CLOSE_2));
149 button->SetImage(views::CustomButton::STATE_HOVERED,
150 rb.GetImageSkiaNamed(IDR_CLOSE_2_H));
151 button->SetImage(views::CustomButton::STATE_PRESSED,
152 rb.GetImageSkiaNamed(IDR_CLOSE_2_P));
153 layout->AddView(button);
156 void AddHeading(GridLayout* layout, const base::string16& heading) {
157 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
158 views::Label* heading_label = new views::Label(
159 heading, rb.GetFontList(ui::ResourceBundle::MediumFont));
160 heading_label->SetMultiLine(true);
161 heading_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
162 heading_label->SizeToFit(kTextColumnWidth);
163 layout->AddView(heading_label);
166 // views::ButtonListener implementation:
167 void ButtonPressed(views::Button* sender, const ui::Event& event) override {
168 GetWidget()->Close();
171 DISALLOW_COPY_AND_ASSIGN(BundleInstalledBubble);
174 } // namespace
176 void BundleInstaller::ShowInstalledBubble(
177 const BundleInstaller* bundle, Browser* browser) {
178 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
179 views::View* anchor = browser_view->GetToolbarView()->app_menu();
180 new BundleInstalledBubble(bundle, anchor, views::BubbleBorder::TOP_RIGHT);