summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/extensions/bundle_installed_bubble.cc
blob: 6aa7d9e7ba958de1eebd2d20215be0ed9fda2b7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// 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/i18n/rtl.h"
#include "base/utf_string_conversions.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_view.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources_standard.h"
#include "grit/ui_resources_standard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/views/bubble/bubble_delegate.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.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 for the bubble.
const int kColumnSetId = 0;

// The width of the left column.
const int kLeftColumnWidth = 325;

// Heading font size correction.
#if defined(CROS_FONTS_USING_BCI)
const int kHeadingFontSizeDelta = 0;
#else
const int kHeadingFontSizeDelta = 1;
#endif

class BundleInstalledBubble : public views::BubbleDelegateView,
                              public views::ButtonListener {
 public:
  BundleInstalledBubble(const BundleInstaller* bundle,
                        View* anchor_view,
                        views::BubbleBorder::ArrowLocation arrow_location)
      : views::BubbleDelegateView(anchor_view, arrow_location) {
    GridLayout* layout = GridLayout::CreatePanel(this);
    SetLayoutManager(layout);
    views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId);

    column_set->AddColumn(GridLayout::LEADING,
                          GridLayout::FILL,
                          0,  // no resizing
                          GridLayout::USE_PREF,
                          0,  // no fixed with
                          kLeftColumnWidth);
    column_set->AddPaddingColumn(0, views::kPanelHorizMargin);
    column_set->AddColumn(GridLayout::LEADING,
                          GridLayout::LEADING,
                          0,  // no resizing
                          GridLayout::USE_PREF,
                          0,  // no fixed width
                          0); // no min width (only holds close button)

    layout->StartRow(0, kColumnSetId);

    AddContent(layout, bundle);
  }

  virtual ~BundleInstalledBubble() {}

 private:
  void AddContent(GridLayout* layout, const BundleInstaller* bundle) {
    string16 installed_heading = bundle->GetHeadingTextFor(
        BundleInstaller::Item::STATE_INSTALLED);
    string16 failed_heading = bundle->GetHeadingTextFor(
        BundleInstaller::Item::STATE_FAILED);

    // Insert the list of installed items.
    if (!installed_heading.empty()) {
      layout->StartRow(0, kColumnSetId);
      AddHeading(layout, installed_heading);
      AddCloseButton(layout, this);
      AddItemList(layout, bundle->GetItemsWithState(
          BundleInstaller::Item::STATE_INSTALLED));

      // Insert a line of padding if we're showing both sections.
      if (!failed_heading.empty())
        layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    }

    // Insert the list of failed items.
    if (!failed_heading.empty()) {
      layout->StartRow(0, kColumnSetId);
      AddHeading(layout, failed_heading);

      // 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 (installed_heading.empty())
        AddCloseButton(layout, this);

      AddItemList(layout, bundle->GetItemsWithState(
          BundleInstaller::Item::STATE_FAILED));
    }

    views::BubbleDelegateView::CreateBubble(this);
    StartFade(true);
  }

  void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) {
    for (size_t i = 0; i < items.size(); ++i) {
      string16 extension_name = UTF8ToUTF16(items[i].localized_name);
      base::i18n::AdjustStringForLocaleDirection(&extension_name);
      layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
      layout->StartRow(0, kColumnSetId);
      views::Label* extension_label = new views::Label(
          l10n_util::GetStringFUTF16(
              IDS_EXTENSION_PERMISSION_LINE, extension_name));
      extension_label->SetMultiLine(true);
      extension_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
      extension_label->SizeToFit(kLeftColumnWidth);
      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::BS_NORMAL,
                     rb.GetImageSkiaNamed(IDR_CLOSE_BAR));
    button->SetImage(views::CustomButton::BS_HOT,
                     rb.GetImageSkiaNamed(IDR_CLOSE_BAR_H));
    button->SetImage(views::CustomButton::BS_PUSHED,
                     rb.GetImageSkiaNamed(IDR_CLOSE_BAR_P));
    layout->AddView(button);
  }

  void AddHeading(GridLayout* layout, const string16& heading) {
    ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    gfx::Font bold_font = rb.GetFont(ui::ResourceBundle::BaseFont).DeriveFont(
        kHeadingFontSizeDelta, gfx::Font::BOLD);

    views::Label* heading_label = new views::Label(heading, bold_font);
    heading_label->SetMultiLine(true);
    heading_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
    heading_label->SizeToFit(kLeftColumnWidth);
    layout->AddView(heading_label);
  }

  // views::ButtonListener implementation:
  virtual void ButtonPressed(views::Button* sender,
                             const views::Event& event) OVERRIDE {
    StartFade(false);
  }

  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();
  new BundleInstalledBubble(bundle, anchor, views::BubbleBorder::TOP_RIGHT);
}