| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2009 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 "chrome/browser/views/extensions/extension_installed_bubble.h" |
| 6 |
| 7 #include "app/l10n_util.h" |
| 8 #include "app/resource_bundle.h" |
| 9 #include "base/message_loop.h" |
| 10 #include "chrome/browser/browser.h" |
| 11 #include "chrome/browser/browser_window.h" |
| 12 #include "chrome/browser/views/browser_actions_container.h" |
| 13 #include "chrome/browser/views/frame/browser_view.h" |
| 14 #include "chrome/browser/views/location_bar_view.h" |
| 15 #include "chrome/browser/views/toolbar_view.h" |
| 16 #include "chrome/common/notification_service.h" |
| 17 #include "chrome/common/notification_type.h" |
| 18 #include "grit/generated_resources.h" |
| 19 #include "views/controls/label.h" |
| 20 #include "views/standard_layout.h" |
| 21 #include "views/view.h" |
| 22 |
| 23 namespace { |
| 24 |
| 25 const int kIconSize = 43; |
| 26 |
| 27 const int kRightColumnWidth = 270; |
| 28 |
| 29 // The InfoBubble uses a BubbleBorder which adds about 6 pixels of whitespace |
| 30 // around the content view. We compensate by reducing our outer borders by this |
| 31 // amount. |
| 32 const int kBubbleBorderInsert = 6; |
| 33 const int kHorizOuterMargin = kPanelHorizMargin - kBubbleBorderInsert; |
| 34 const int kVertOuterMargin = kPanelVertMargin - kBubbleBorderInsert; |
| 35 |
| 36 // InstalledBubbleContent is the content view which is placed in the |
| 37 // ExtensionInstalledBubble. It displays the install icon and explanatory |
| 38 // text about the installed extension. |
| 39 class InstalledBubbleContent : public views::View { |
| 40 public: |
| 41 InstalledBubbleContent(Extension* extension, |
| 42 ExtensionInstalledBubble::BubbleType type, |
| 43 SkBitmap* icon) |
| 44 : type_(type), |
| 45 info_(NULL) { |
| 46 const gfx::Font& font = |
| 47 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont); |
| 48 |
| 49 // Scale down to 43x43, but allow smaller icons (don't scale up). |
| 50 gfx::Size size(icon->width(), icon->height()); |
| 51 if (size.width() > kIconSize || size.height() > kIconSize) |
| 52 size = gfx::Size(kIconSize, kIconSize); |
| 53 icon_ = new views::ImageView(); |
| 54 icon_->SetImageSize(size); |
| 55 icon_->SetImage(*icon); |
| 56 AddChildView(icon_); |
| 57 |
| 58 heading_ = new views::Label( |
| 59 l10n_util::GetStringF(IDS_EXTENSION_INSTALLED_HEADING, |
| 60 UTF8ToWide(extension->name()))); |
| 61 heading_->SetFont(font.DeriveFont(3, gfx::Font::NORMAL)); |
| 62 heading_->SetMultiLine(true); |
| 63 heading_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 64 AddChildView(heading_); |
| 65 |
| 66 if (type_ == ExtensionInstalledBubble::PAGE_ACTION) { |
| 67 info_ = new views::Label(l10n_util::GetString( |
| 68 IDS_EXTENSION_INSTALLED_PAGE_ACTION_INFO)); |
| 69 info_->SetFont(font); |
| 70 info_->SetMultiLine(true); |
| 71 info_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 72 AddChildView(info_); |
| 73 } |
| 74 |
| 75 manage_ = new views::Label(l10n_util::GetString( |
| 76 IDS_EXTENSION_INSTALLED_MANAGE_INFO)); |
| 77 manage_->SetFont(font); |
| 78 manage_->SetMultiLine(true); |
| 79 manage_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
| 80 AddChildView(manage_); |
| 81 } |
| 82 |
| 83 private: |
| 84 virtual gfx::Size GetPreferredSize() { |
| 85 int width = kRightColumnWidth + kHorizOuterMargin + kHorizOuterMargin; |
| 86 width += kIconSize; |
| 87 width += kPanelHorizMargin; |
| 88 |
| 89 int height = kVertOuterMargin * 2; |
| 90 height += heading_->GetHeightForWidth(kRightColumnWidth); |
| 91 height += kPanelVertMargin; |
| 92 if (type_ == ExtensionInstalledBubble::PAGE_ACTION) { |
| 93 height += info_->GetHeightForWidth(kRightColumnWidth); |
| 94 height += kPanelVertMargin; |
| 95 } |
| 96 height += manage_->GetHeightForWidth(kRightColumnWidth); |
| 97 |
| 98 return gfx::Size(width, std::max(height, kIconSize + kVertOuterMargin * 2)); |
| 99 } |
| 100 |
| 101 virtual void Layout() { |
| 102 int x = kHorizOuterMargin; |
| 103 int y = kVertOuterMargin; |
| 104 |
| 105 icon_->SetBounds(x, y, kIconSize, kIconSize); |
| 106 x += kIconSize; |
| 107 x += kPanelHorizMargin; |
| 108 |
| 109 heading_->SizeToFit(kRightColumnWidth); |
| 110 heading_->SetX(x); |
| 111 heading_->SetY(y); |
| 112 y += heading_->height(); |
| 113 y += kPanelVertMargin; |
| 114 |
| 115 if (type_ == ExtensionInstalledBubble::PAGE_ACTION) { |
| 116 info_->SizeToFit(kRightColumnWidth); |
| 117 info_->SetX(x); |
| 118 info_->SetY(y); |
| 119 y += info_->height(); |
| 120 y += kPanelVertMargin; |
| 121 } |
| 122 |
| 123 manage_->SizeToFit(kRightColumnWidth); |
| 124 manage_->SetX(x); |
| 125 manage_->SetY(y); |
| 126 } |
| 127 |
| 128 ExtensionInstalledBubble::BubbleType type_; |
| 129 views::ImageView* icon_; |
| 130 views::Label* heading_; |
| 131 views::Label* info_; |
| 132 views::Label* manage_; |
| 133 |
| 134 DISALLOW_COPY_AND_ASSIGN(InstalledBubbleContent); |
| 135 }; |
| 136 |
| 137 } // namespace |
| 138 |
| 139 void ExtensionInstalledBubble::Show(Extension *extension, Browser *browser, |
| 140 SkBitmap icon) { |
| 141 new ExtensionInstalledBubble(extension, browser, icon); |
| 142 } |
| 143 |
| 144 ExtensionInstalledBubble::ExtensionInstalledBubble(Extension *extension, |
| 145 Browser *browser, |
| 146 SkBitmap icon) |
| 147 : extension_(extension), |
| 148 browser_(browser), |
| 149 icon_(icon) { |
| 150 AddRef(); // Balanced in InfoBubbleClosing. |
| 151 |
| 152 if (extension_->browser_action()) { |
| 153 type_ = BROWSER_ACTION; |
| 154 } else if (extension->page_action() && |
| 155 !extension->page_action()->default_icon_path().empty()) { |
| 156 type_ = PAGE_ACTION; |
| 157 } else { |
| 158 type_ = GENERIC; |
| 159 } |
| 160 |
| 161 // |extension| has been initialized but not loaded at this point. We need |
| 162 // to wait on showing the Bubble until not only the EXTENSION_LOADED gets |
| 163 // fired, but all of the EXTENSION_LOADED Observers have run. Only then can we |
| 164 // be sure that a BrowserAction or PageAction has had views created which we |
| 165 // can inspect for the purpose of previewing of pointing to them. |
| 166 registrar_.Add(this, NotificationType::EXTENSION_LOADED, |
| 167 NotificationService::AllSources()); |
| 168 } |
| 169 |
| 170 void ExtensionInstalledBubble::Observe(NotificationType type, |
| 171 const NotificationSource& source, |
| 172 const NotificationDetails& details) { |
| 173 if (type == NotificationType::EXTENSION_LOADED) { |
| 174 Extension* extension = Details<Extension>(details).ptr(); |
| 175 if (extension == extension_) { |
| 176 // PostTask to ourself to allow all EXTENSION_LOADED Observers to run. |
| 177 MessageLoopForUI::current()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 178 &ExtensionInstalledBubble::ShowInternal)); |
| 179 } |
| 180 } else { |
| 181 NOTREACHED() << L"Received unexpected notification"; |
| 182 } |
| 183 } |
| 184 |
| 185 void ExtensionInstalledBubble::ShowInternal() { |
| 186 BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( |
| 187 browser_->window()->GetNativeHandle()); |
| 188 |
| 189 views::View* reference_view = NULL; |
| 190 if (type_ == BROWSER_ACTION) { |
| 191 reference_view = browser_view->GetToolbarView()->browser_actions() |
| 192 ->GetBrowserActionView(extension_); |
| 193 DCHECK(reference_view); |
| 194 } else if (type_ == PAGE_ACTION) { |
| 195 LocationBarView* location_bar_view = browser_view->GetLocationBarView(); |
| 196 location_bar_view->SetPreviewEnabledPageAction(extension_->page_action(), |
| 197 true); // preview_enabled |
| 198 reference_view = location_bar_view->GetPageActionView( |
| 199 extension_->page_action()); |
| 200 DCHECK(reference_view); |
| 201 } |
| 202 |
| 203 // Default case. |
| 204 if (reference_view == NULL) |
| 205 reference_view = browser_view->GetToolbarView()->app_menu(); |
| 206 |
| 207 gfx::Point origin; |
| 208 views::View::ConvertPointToScreen(reference_view, &origin); |
| 209 gfx::Rect bounds = reference_view->bounds(); |
| 210 bounds.set_x(origin.x()); |
| 211 bounds.set_y(origin.y()); |
| 212 |
| 213 views::View* bubble_content = new InstalledBubbleContent(extension_, type_, |
| 214 &icon_); |
| 215 InfoBubble::Show(browser_view->GetWindow(), bounds, bubble_content, this); |
| 216 } |
| 217 |
| 218 // InfoBubbleDelegate |
| 219 void ExtensionInstalledBubble::InfoBubbleClosing(InfoBubble* info_bubble, |
| 220 bool closed_by_escape) { |
| 221 if (extension_->page_action()) { |
| 222 BrowserView* browser_view = BrowserView::GetBrowserViewForNativeWindow( |
| 223 browser_->window()->GetNativeHandle()); |
| 224 browser_view->GetLocationBarView()->SetPreviewEnabledPageAction( |
| 225 extension_->page_action(), |
| 226 false); // preview_enabled |
| 227 } |
| 228 Release(); // Balanced in ctor. |
| 229 } |
| OLD | NEW |