bundle_installed_bubble.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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. 4 5#include "base/i18n/rtl.h" 6#include "base/strings/utf_string_conversions.h" 7#include "chrome/browser/extensions/bundle_installer.h" 8#include "chrome/browser/ui/browser.h" 9#include "chrome/browser/ui/views/frame/browser_view.h" 10#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 11#include "grit/generated_resources.h" 12#include "grit/theme_resources.h" 13#include "ui/base/l10n/l10n_util.h" 14#include "ui/base/resource/resource_bundle.h" 15#include "ui/resources/grit/ui_resources.h" 16#include "ui/views/bubble/bubble_delegate.h" 17#include "ui/views/controls/button/image_button.h" 18#include "ui/views/controls/image_view.h" 19#include "ui/views/controls/label.h" 20#include "ui/views/layout/grid_layout.h" 21#include "ui/views/layout/layout_constants.h" 22 23using extensions::BundleInstaller; 24using views::GridLayout; 25 26namespace { 27 28// The ID of the column set for the bubble. 29const int kColumnSetId = 0; 30 31// The width of the left column. 32const int kLeftColumnWidth = 325; 33 34class BundleInstalledBubble : public views::BubbleDelegateView, 35 public views::ButtonListener { 36 public: 37 BundleInstalledBubble(const BundleInstaller* bundle, 38 View* anchor_view, 39 views::BubbleBorder::Arrow arrow) 40 : views::BubbleDelegateView(anchor_view, arrow) { 41 GridLayout* layout = GridLayout::CreatePanel(this); 42 SetLayoutManager(layout); 43 views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId); 44 45 column_set->AddColumn(GridLayout::LEADING, 46 GridLayout::FILL, 47 0, // no resizing 48 GridLayout::USE_PREF, 49 0, // no fixed with 50 kLeftColumnWidth); 51 column_set->AddPaddingColumn(0, views::kPanelHorizMargin); 52 column_set->AddColumn(GridLayout::LEADING, 53 GridLayout::LEADING, 54 0, // no resizing 55 GridLayout::USE_PREF, 56 0, // no fixed width 57 0); // no min width (only holds close button) 58 59 layout->StartRow(0, kColumnSetId); 60 61 AddContent(layout, bundle); 62 } 63 64 virtual ~BundleInstalledBubble() {} 65 66 private: 67 void AddContent(GridLayout* layout, const BundleInstaller* bundle) { 68 base::string16 installed_heading = bundle->GetHeadingTextFor( 69 BundleInstaller::Item::STATE_INSTALLED); 70 base::string16 failed_heading = bundle->GetHeadingTextFor( 71 BundleInstaller::Item::STATE_FAILED); 72 73 // Insert the list of installed items. 74 if (!installed_heading.empty()) { 75 layout->StartRow(0, kColumnSetId); 76 AddHeading(layout, installed_heading); 77 AddCloseButton(layout, this); 78 AddItemList(layout, bundle->GetItemsWithState( 79 BundleInstaller::Item::STATE_INSTALLED)); 80 81 // Insert a line of padding if we're showing both sections. 82 if (!failed_heading.empty()) 83 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 84 } 85 86 // Insert the list of failed items. 87 if (!failed_heading.empty()) { 88 layout->StartRow(0, kColumnSetId); 89 AddHeading(layout, failed_heading); 90 91 // The close button should be in the second column of the first row, so 92 // we add it here if there was no installed items section. 93 if (installed_heading.empty()) 94 AddCloseButton(layout, this); 95 96 AddItemList(layout, bundle->GetItemsWithState( 97 BundleInstaller::Item::STATE_FAILED)); 98 } 99 100 views::BubbleDelegateView::CreateBubble(this)->Show(); 101 } 102 103 void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) { 104 for (size_t i = 0; i < items.size(); ++i) { 105 base::string16 extension_name = 106 base::UTF8ToUTF16(items[i].localized_name); 107 base::i18n::AdjustStringForLocaleDirection(&extension_name); 108 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 109 layout->StartRow(0, kColumnSetId); 110 views::Label* extension_label = new views::Label( 111 l10n_util::GetStringFUTF16( 112 IDS_EXTENSION_PERMISSION_LINE, extension_name)); 113 extension_label->SetMultiLine(true); 114 extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 115 extension_label->SizeToFit(kLeftColumnWidth); 116 layout->AddView(extension_label); 117 } 118 } 119 120 void AddCloseButton(GridLayout* layout, views::ButtonListener* listener) { 121 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 122 123 views::ImageButton* button = new views::ImageButton(listener); 124 button->SetImage(views::CustomButton::STATE_NORMAL, 125 rb.GetImageSkiaNamed(IDR_CLOSE_2)); 126 button->SetImage(views::CustomButton::STATE_HOVERED, 127 rb.GetImageSkiaNamed(IDR_CLOSE_2_H)); 128 button->SetImage(views::CustomButton::STATE_PRESSED, 129 rb.GetImageSkiaNamed(IDR_CLOSE_2_P)); 130 layout->AddView(button); 131 } 132 133 void AddHeading(GridLayout* layout, const base::string16& heading) { 134 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 135 views::Label* heading_label = new views::Label( 136 heading, rb.GetFontList(ui::ResourceBundle::MediumFont)); 137 heading_label->SetMultiLine(true); 138 heading_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); 139 heading_label->SizeToFit(kLeftColumnWidth); 140 layout->AddView(heading_label); 141 } 142 143 // views::ButtonListener implementation: 144 virtual void ButtonPressed(views::Button* sender, 145 const ui::Event& event) OVERRIDE { 146 GetWidget()->Close(); 147 } 148 149 DISALLOW_COPY_AND_ASSIGN(BundleInstalledBubble); 150}; 151 152} // namespace 153 154void BundleInstaller::ShowInstalledBubble( 155 const BundleInstaller* bundle, Browser* browser) { 156 BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); 157 views::View* anchor = browser_view->GetToolbarView()->app_menu(); 158 new BundleInstalledBubble(bundle, anchor, views::BubbleBorder::TOP_RIGHT); 159} 160