diff options
author | mihaip@chromium.org <mihaip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-06 04:33:13 +0000 |
---|---|---|
committer | mihaip@chromium.org <mihaip@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-09-06 04:33:13 +0000 |
commit | 0e4ee1bde8c498c0986aacc868396d7d5b2711c8 (patch) | |
tree | 0c301fed95b55d5215a410ff99b6ca459e12299c /chrome/browser/ui | |
parent | 1eb5a2298dbc3dc3d30272847cdaa3e6b4d2791d (diff) | |
download | chromium_src-0e4ee1bde8c498c0986aacc868396d7d5b2711c8.zip chromium_src-0e4ee1bde8c498c0986aacc868396d7d5b2711c8.tar.gz chromium_src-0e4ee1bde8c498c0986aacc868396d7d5b2711c8.tar.bz2 |
Implement the inline extensions/apps install UI for Cocoa.
This required a new .xib (ExtensionInstallPromptInline) that shows store data
(star rating, number of reviews, number of users). Current .xibs
(ExtensionInstallPrompt and ExtensionInstallPromptNoWarnings) were rearranged
slightly to have the icon on the right and use a bulleted list for the list
of permissions (instead of a box) per Cole's mock.
This is the Cocoa side of r99407 (views) and r99205 (GTK).
BUG=93380
TEST=no
Review URL: http://codereview.chromium.org/7835039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@99695 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui')
5 files changed, 240 insertions, 115 deletions
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h index 49aaaef..4c0a9ba 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h @@ -10,7 +10,7 @@ #import <Cocoa/Cocoa.h> -#include "base/memory/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "chrome/browser/extensions/extension_install_ui.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -24,31 +24,38 @@ class Profile; @private IBOutlet NSImageView* iconView_; IBOutlet NSTextField* titleField_; - IBOutlet NSTextField* subtitleField_; - IBOutlet NSTextField* warningsField_; - IBOutlet NSBox* warningsBox_; IBOutlet NSButton* cancelButton_; IBOutlet NSButton* okButton_; + // Present only when the dialog has permission warnings to display. + IBOutlet NSTextField* subtitleField_; + IBOutlet NSTextField* warningsField_; + + // Present only in the inline install dialog. + IBOutlet NSBox* warningsSeparator_; // Only when there are permissions. + IBOutlet NSView* ratingStars_; + IBOutlet NSTextField* ratingCountField_; + IBOutlet NSTextField* userCountField_; + NSWindow* parentWindow_; // weak Profile* profile_; // weak ExtensionInstallUI::Delegate* delegate_; // weak - - scoped_nsobject<NSString> title_; - scoped_nsobject<NSString> warnings_; - scoped_nsobject<NSString> button_; - scoped_nsobject<NSString> cancel_button_; - scoped_nsobject<NSString> subtitle_; + const Extension* extension_; // weak + scoped_ptr<ExtensionInstallUI::Prompt> prompt_; SkBitmap icon_; } +// For unit test use only @property(nonatomic, readonly) NSImageView* iconView; @property(nonatomic, readonly) NSTextField* titleField; @property(nonatomic, readonly) NSTextField* subtitleField; @property(nonatomic, readonly) NSTextField* warningsField; -@property(nonatomic, readonly) NSBox* warningsBox; @property(nonatomic, readonly) NSButton* cancelButton; @property(nonatomic, readonly) NSButton* okButton; +@property(nonatomic, readonly) NSBox* warningsSeparator; +@property(nonatomic, readonly) NSView* ratingStars; +@property(nonatomic, readonly) NSTextField* ratingCountField; +@property(nonatomic, readonly) NSTextField* userCountField; - (id)initWithParentWindow:(NSWindow*)window profile:(Profile*)profile @@ -57,6 +64,7 @@ class Profile; icon:(SkBitmap*)bitmap prompt:(const ExtensionInstallUI::Prompt&)prompt; - (void)runAsModalSheet; +- (IBAction)storeLinkClicked:(id)sender; // Callback for "View details" link. - (IBAction)cancel:(id)sender; - (IBAction)ok:(id)sender; diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm index cd383ee..a64dcc5 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm @@ -5,6 +5,7 @@ #import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.h" #include "base/mac/mac_util.h" +#include "base/memory/scoped_nsobject.h" #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "base/utf_string_conversions.h" @@ -15,11 +16,21 @@ #include "chrome/common/extensions/extension.h" #include "grit/generated_resources.h" #include "skia/ext/skia_utils_mac.h" +#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" +@interface ExtensionInstallDialogController () +- (bool)isInlineInstall; +- (void)appendRatingStar:(const SkBitmap*)skiaImage; +@end + namespace { +// Padding above the warnings separator, we must also subtract this when hiding +// it. +const CGFloat kWarningsSeparatorPadding = 14; + // Maximum height we will adjust controls to when trying to accomodate their // contents. const CGFloat kMaxControlHeight = 400; @@ -45,6 +56,12 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { [control setFrameOrigin:origin]; } +void AppendRatingStarsShim(const SkBitmap* skiaImage, void* data) { + ExtensionInstallDialogController* controller = + static_cast<ExtensionInstallDialogController*>(data); + [controller appendRatingStar:skiaImage]; +} + } @implementation ExtensionInstallDialogController @@ -53,9 +70,12 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { @synthesize titleField = titleField_; @synthesize subtitleField = subtitleField_; @synthesize warningsField = warningsField_; -@synthesize warningsBox= warningsBox_; @synthesize cancelButton = cancelButton_; @synthesize okButton = okButton_; +@synthesize warningsSeparator = warningsSeparator_; +@synthesize ratingStars = ratingStars_; +@synthesize ratingCountField = ratingCountField_; +@synthesize userCountField = userCountField_; - (id)initWithParentWindow:(NSWindow*)window profile:(Profile*)profile @@ -65,9 +85,14 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { prompt:(const ExtensionInstallUI::Prompt&)prompt { NSString* nibpath = nil; - // We use a different XIB in the case of no permission warnings, that is a - // little bit more nicely laid out. - if (prompt.GetPermissionCount() == 0) { + // We use a different XIB in the case of inline installs or no permission + // warnings, that respectively show webstore ratings data and are a more + // nicely laid out. + if (prompt.type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT) { + nibpath = [base::mac::MainAppBundle() + pathForResource:@"ExtensionInstallPromptInline" + ofType:@"nib"]; + } else if (prompt.GetPermissionCount() == 0) { nibpath = [base::mac::MainAppBundle() pathForResource:@"ExtensionInstallPromptNoWarnings" ofType:@"nib"]; @@ -82,32 +107,8 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { profile_ = profile; icon_ = *icon; delegate_ = delegate; - - title_.reset([base::SysUTF16ToNSString( - prompt.GetHeading(extension->name())) retain]); - subtitle_.reset([base::SysUTF16ToNSString( - prompt.GetPermissionsHeader()) retain]); - button_.reset([base::SysUTF16ToNSString( - prompt.GetAcceptButtonLabel()) retain]); - NSString* cancel_button_label = prompt.HasAbortButtonLabel() ? - base::SysUTF16ToNSString(prompt.GetAbortButtonLabel()) : - l10n_util::GetNSString(IDS_CANCEL); - cancel_button_.reset([cancel_button_label retain]); - - // We display the permission warnings as a simple text string, separated by - // newlines. - if (prompt.GetPermissionCount()) { - string16 joined_warnings; - for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { - if (i > 0) - joined_warnings += UTF8ToUTF16("\n\n"); - - joined_warnings += prompt.GetPermission(i); - } - - warnings_.reset( - [base::SysUTF16ToNSString(joined_warnings) retain]); - } + extension_ = extension; + prompt_.reset(new ExtensionInstallUI::Prompt(prompt)); } return self; } @@ -120,8 +121,18 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { contextInfo:nil]; } +- (IBAction)storeLinkClicked:(id)sender { + GURL store_url( + extension_urls::GetWebstoreItemDetailURLPrefix() + extension_->id()); + BrowserList::GetLastActiveWithProfile(profile_)-> + OpenURL(store_url, GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); + + delegate_->InstallUIAbort(/*user_initiated=*/true); + [NSApp endSheet:[self window]]; +} + - (IBAction)cancel:(id)sender { - delegate_->InstallUIAbort(true); + delegate_->InstallUIAbort(/*user_initiated=*/true); [NSApp endSheet:[self window]]; } @@ -131,15 +142,30 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { } - (void)awakeFromNib { - [titleField_ setStringValue:title_.get()]; - [subtitleField_ setStringValue:subtitle_.get()]; - [okButton_ setTitle:button_.get()]; - [cancelButton_ setTitle:cancel_button_.get()]; + // Make sure we're the window's delegate as set in the nib. + DCHECK_EQ(self, static_cast<ExtensionInstallDialogController*>( + [[self window] delegate])); + + // Set control labels. + [titleField_ setStringValue:base::SysUTF16ToNSString( + prompt_->GetHeading(extension_->name()))]; + [okButton_ setTitle:base::SysUTF16ToNSString( + prompt_->GetAcceptButtonLabel())]; + [cancelButton_ setTitle:prompt_->HasAbortButtonLabel() ? + base::SysUTF16ToNSString(prompt_->GetAbortButtonLabel()) : + l10n_util::GetNSString(IDS_CANCEL)]; + if ([self isInlineInstall]) { + prompt_->AppendRatingStars(AppendRatingStarsShim, self); + [ratingCountField_ setStringValue:base::SysUTF16ToNSString( + prompt_->GetRatingCount())]; + [userCountField_ setStringValue:base::SysUTF16ToNSString( + prompt_->GetUserCount())]; + } NSImage* image = gfx::SkBitmapToNSImage(icon_); [iconView_ setImage:image]; - // Reisze |titleField_| to fit title + // Resize |titleField_| to fit the title. CGFloat originalTitleWidth = [titleField_ frame].size.width; [titleField_ sizeToFit]; CGFloat newTitleWidth = [titleField_ frame].size.width; @@ -149,47 +175,81 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { [[self window] setFrame:frame display:NO]; } - // Make sure we're the window's delegate as set in the nib. - DCHECK_EQ(self, static_cast<ExtensionInstallDialogController*>( - [[self window] delegate])); + // Resize |okButton_| and |cancelButton_| to fit the button labels, but keep + // them right-aligned. + NSSize buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:okButton_]; + if (buttonDelta.width) { + [okButton_ setFrame:NSOffsetRect([okButton_ frame], -buttonDelta.width, 0)]; + [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], + -buttonDelta.width, 0)]; + } + buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; + if (buttonDelta.width) { + [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], + -buttonDelta.width, 0)]; + } + CGFloat totalOffset = 0.0; // If there are any warnings, then we have to do some special layout. - if ([warnings_.get() length] > 0) { - [warningsField_ setStringValue:warnings_.get()]; + if (prompt_->GetPermissionCount() > 0) { + [subtitleField_ setStringValue:base::SysUTF16ToNSString( + prompt_->GetPermissionsHeader())]; + + // We display the permission warnings as a simple text string, separated by + // newlines. + NSMutableString* joinedWarnings = [NSMutableString string]; + for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) { + if (i > 0) + [joinedWarnings appendString:@"\n"]; + [joinedWarnings appendString:base::SysUTF16ToNSString( + prompt_->GetPermission(i))]; + } + [warningsField_ setStringValue:joinedWarnings]; // The dialog is laid out in the NIB exactly how we want it assuming that // each label fits on one line. However, for each label, we want to allow // wrapping onto multiple lines. So we accumulate an offset by measuring how - // big each label wants to be, and comparing it to how bit it actually is. + // big each label wants to be, and comparing it to how big it actually is. // Then we shift each label down and resize by the appropriate amount, then // finally resize the window. - CGFloat totalOffset = 0.0; - // Text fields. - totalOffset += AdjustControlHeightToFitContent(titleField_); - OffsetControlVertically(titleField_, -totalOffset); + // Additionally, in the store version of the dialog the icon extends past + // the one-line version of the permission field. Therefore when increasing + // the window size for multi-line permissions we don't have to add the full + // offset, only the part that extends past the icon. + CGFloat warningsGrowthSlack = 0; + if ([warningsField_ frame].origin.y > [iconView_ frame].origin.y) { + warningsGrowthSlack = + [warningsField_ frame].origin.y - [iconView_ frame].origin.y; + } totalOffset += AdjustControlHeightToFitContent(subtitleField_); OffsetControlVertically(subtitleField_, -totalOffset); - CGFloat warningsOffset = AdjustControlHeightToFitContent(warningsField_); - OffsetControlVertically(warningsField_, -warningsOffset); - totalOffset += warningsOffset; - - NSRect warningsBoxRect = [warningsBox_ frame]; - warningsBoxRect.origin.y -= totalOffset; - warningsBoxRect.size.height += warningsOffset; - [warningsBox_ setFrame:warningsBoxRect]; - - // buttons are positioned automatically in the XIB. + totalOffset += AdjustControlHeightToFitContent(warningsField_); + OffsetControlVertically(warningsField_, -totalOffset); + totalOffset = MAX(totalOffset - warningsGrowthSlack, 0); + } else if ([self isInlineInstall]) { + // Inline installs that don't have a permissions section need to hide + // controls related to that and shrink the window by the space they take + // up. + NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame], + [subtitleField_ frame]); + hiddenRect = NSUnionRect(hiddenRect, [warningsField_ frame]); + [warningsSeparator_ setHidden:YES]; + [subtitleField_ setHidden:YES]; + [warningsField_ setHidden:YES]; + totalOffset -= hiddenRect.size.height + kWarningsSeparatorPadding; + } - // Finally, adjust the window size. + // If necessary, adjust the window size. + if (totalOffset) { NSRect currentRect = [[self window] frame]; [[self window] setFrame:NSMakeRect(currentRect.origin.x, currentRect.origin.y - totalOffset, currentRect.size.width, currentRect.size.height + totalOffset) - display:NO]; + display:NO]; } } @@ -203,6 +263,28 @@ void OffsetControlVertically(NSControl* control, CGFloat amount) { [self autorelease]; } +- (bool)isInlineInstall { + return prompt_->type() == ExtensionInstallUI::INLINE_INSTALL_PROMPT; +} + +- (void)appendRatingStar:(const SkBitmap*)skiaImage { + NSImage* image = gfx::SkBitmapToNSImageWithColorSpace( + *skiaImage, base::mac::GetSystemColorSpace()); + NSRect frame = NSMakeRect(0, 0, skiaImage->width(), skiaImage->height()); + scoped_nsobject<NSImageView> view([[NSImageView alloc] initWithFrame:frame]); + [view setImage:image]; + + // Add this star after all the other ones + CGFloat maxStarRight = 0; + if ([[ratingStars_ subviews] count]) { + maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]); + } + NSRect starBounds = NSMakeRect(maxStarRight, 0, + skiaImage->width(), skiaImage->height()); + [view setFrame:starBounds]; + [ratingStars_ addSubview:view]; +} + @end // ExtensionInstallDialogController void ShowExtensionInstallDialog( @@ -234,5 +316,6 @@ void ShowExtensionInstallDialog( icon:icon prompt:prompt]; + // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455) [controller runAsModalSheet]; } diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm index c29cbf6..2b96839 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller_unittest.mm @@ -104,8 +104,7 @@ class MockExtensionInstallUIDelegate : public ExtensionInstallUI::Delegate { // Test that we can load the two kinds of prompts correctly, that the outlets // are hooked up, and that the dialog calls cancel when cancel is pressed. TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { - scoped_ptr<MockExtensionInstallUIDelegate> delegate( - new MockExtensionInstallUIDelegate); + MockExtensionInstallUIDelegate delegate; ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); std::vector<string16> permissions; @@ -117,7 +116,7 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { initWithParentWindow:test_window() profile:helper_.profile() extension:extension_.get() - delegate:delegate.get() + delegate:&delegate icon:&icon_ prompt:prompt]); @@ -144,8 +143,6 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { EXPECT_NSEQ([[controller warningsField] stringValue], base::SysUTF16ToNSString(prompt.GetPermission(0))); - EXPECT_TRUE([controller warningsBox] != nil); - EXPECT_TRUE([controller cancelButton] != nil); EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]); EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]); @@ -156,14 +153,13 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalCancel) { // Test that cancel calls our delegate. [controller cancel:nil]; - EXPECT_EQ(1, delegate->abort_count()); - EXPECT_EQ(0, delegate->proceed_count()); + EXPECT_EQ(1, delegate.abort_count()); + EXPECT_EQ(0, delegate.proceed_count()); } TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalOK) { - scoped_ptr<MockExtensionInstallUIDelegate> delegate( - new MockExtensionInstallUIDelegate); + MockExtensionInstallUIDelegate delegate; ExtensionInstallUI::Prompt prompt(ExtensionInstallUI::INSTALL_PROMPT); std::vector<string16> permissions; @@ -175,24 +171,22 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsNormalOK) { initWithParentWindow:test_window() profile:helper_.profile() extension:extension_.get() - delegate:delegate.get() + delegate:&delegate icon:&icon_ prompt:prompt]); [controller window]; // force nib load [controller ok:nil]; - EXPECT_EQ(0, delegate->abort_count()); - EXPECT_EQ(1, delegate->proceed_count()); + EXPECT_EQ(0, delegate.abort_count()); + EXPECT_EQ(1, delegate.proceed_count()); } // Test that controls get repositioned when there are two warnings vs one // warning. TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { - scoped_ptr<MockExtensionInstallUIDelegate> delegate1( - new MockExtensionInstallUIDelegate); - scoped_ptr<MockExtensionInstallUIDelegate> delegate2( - new MockExtensionInstallUIDelegate); + MockExtensionInstallUIDelegate delegate1; + MockExtensionInstallUIDelegate delegate2; ExtensionInstallUI::Prompt one_warning_prompt( ExtensionInstallUI::INSTALL_PROMPT); @@ -210,7 +204,7 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { initWithParentWindow:test_window() profile:helper_.profile() extension:extension_.get() - delegate:delegate1.get() + delegate:&delegate1 icon:&icon_ prompt:one_warning_prompt]); @@ -221,7 +215,7 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { initWithParentWindow:test_window() profile:helper_.profile() extension:extension_.get() - delegate:delegate2.get() + delegate:&delegate2 icon:&icon_ prompt:two_warnings_prompt]); @@ -236,12 +230,6 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { ASSERT_LT([[controller1 warningsField] frame].size.height, [[controller2 warningsField] frame].size.height); - ASSERT_LT([[controller1 warningsBox] frame].size.height, - [[controller2 warningsBox] frame].size.height); - - ASSERT_EQ([[controller1 warningsBox] frame].origin.y, - [[controller2 warningsBox] frame].origin.y); - ASSERT_LT([[controller1 subtitleField] frame].origin.y, [[controller2 subtitleField] frame].origin.y); @@ -252,21 +240,18 @@ TEST_F(ExtensionInstallDialogControllerTest, MultipleWarnings) { // Test that we can load the skinny prompt correctly, and that the outlets are // are hooked up. TEST_F(ExtensionInstallDialogControllerTest, BasicsSkinny) { - scoped_ptr<MockExtensionInstallUIDelegate> delegate( - new MockExtensionInstallUIDelegate); + MockExtensionInstallUIDelegate delegate; // No warnings should trigger skinny prompt. ExtensionInstallUI::Prompt no_warnings_prompt( ExtensionInstallUI::INSTALL_PROMPT); - std::vector<string16> warnings; - scoped_nsobject<ExtensionInstallDialogController> controller([[ExtensionInstallDialogController alloc] initWithParentWindow:test_window() profile:helper_.profile() extension:extension_.get() - delegate:delegate.get() + delegate:&delegate icon:&icon_ prompt:no_warnings_prompt]); @@ -294,5 +279,63 @@ TEST_F(ExtensionInstallDialogControllerTest, BasicsSkinny) { EXPECT_TRUE([controller subtitleField] == nil); EXPECT_TRUE([controller warningsField] == nil); - EXPECT_TRUE([controller warningsBox] == nil); +} + + +// Test that we can load the inline prompt correctly, and that the outlets are +// are hooked up. +TEST_F(ExtensionInstallDialogControllerTest, BasicsInline) { + MockExtensionInstallUIDelegate delegate; + + // No warnings should trigger skinny prompt. + ExtensionInstallUI::Prompt inline_prompt( + ExtensionInstallUI::INLINE_INSTALL_PROMPT); + inline_prompt.SetInlineInstallWebstoreData("1,000", 3.5, 200); + + scoped_nsobject<ExtensionInstallDialogController> + controller([[ExtensionInstallDialogController alloc] + initWithParentWindow:test_window() + profile:helper_.profile() + extension:extension_.get() + delegate:&delegate + icon:&icon_ + prompt:inline_prompt]); + + [controller window]; // force nib load + + // Test the right nib loaded. + EXPECT_NSEQ(@"ExtensionInstallPromptInline", [controller windowNibName]); + + // Check all the controls. + EXPECT_TRUE([controller iconView] != nil); + EXPECT_TRUE([[controller iconView] image] != nil); + + EXPECT_TRUE([controller titleField] != nil); + EXPECT_NE(0u, [[[controller titleField] stringValue] length]); + + EXPECT_TRUE([controller cancelButton] != nil); + EXPECT_NE(0u, [[[controller cancelButton] stringValue] length]); + EXPECT_NE('^', [[[controller cancelButton] stringValue] characterAtIndex:0]); + + EXPECT_TRUE([controller okButton] != nil); + EXPECT_NE(0u, [[[controller okButton] stringValue] length]); + EXPECT_NE('^', [[[controller okButton] stringValue] characterAtIndex:0]); + + EXPECT_TRUE([controller ratingStars] != nil); + EXPECT_EQ(5u, [[[controller ratingStars] subviews] count]); + + EXPECT_TRUE([controller ratingCountField] != nil); + EXPECT_NE(0u, [[[controller ratingCountField] stringValue] length]); + + EXPECT_TRUE([controller userCountField] != nil); + EXPECT_NE(0u, [[[controller userCountField] stringValue] length]); + + // Though we have no permissions warnings, these should still be hooked up, + // just invisible. + EXPECT_TRUE([controller subtitleField] != nil); + EXPECT_TRUE([[controller subtitleField] isHidden]); + EXPECT_TRUE([controller warningsField] != nil); + EXPECT_TRUE([[controller warningsField] isHidden]); + EXPECT_TRUE([controller warningsSeparator] != nil); + EXPECT_TRUE([[controller warningsSeparator] isHidden]); } diff --git a/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc b/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc index 00028b3..2e05f8b 100644 --- a/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/extensions/extension_install_dialog_gtk.cc @@ -32,15 +32,13 @@ const int kPermissionsPadding = 2; const double kRatingTextSize = 12.1; // 12.1px = 9pt @ 96dpi -// Loads an image and adds it as an icon control to the given container. -GtkWidget* AddResourceIcon(int resource_id, GtkWidget* container) { - const SkBitmap* icon = ResourceBundle::GetSharedInstance().GetBitmapNamed( - resource_id); +// Adds a Skia image as an icon control to the given container. +void AddResourceIcon(const SkBitmap* icon, void* data) { + GtkWidget* container = static_cast<GtkWidget*>(data); GdkPixbuf* icon_pixbuf = gfx::GdkPixbufFromSkBitmap(icon); GtkWidget* icon_widget = gtk_image_new_from_pixbuf(icon_pixbuf); g_object_unref(icon_pixbuf); gtk_box_pack_start(GTK_BOX(container), icon_widget, FALSE, FALSE, 0); - return icon_widget; } // Displays the dialog when constructed, deletes itself when dialog is @@ -129,10 +127,7 @@ ExtensionInstallDialog::ExtensionInstallDialog( // Average rating (as stars) and number of ratings GtkWidget* stars_hbox = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(heading_vbox), stars_hbox, FALSE, FALSE, 0); - prompt.AppendRatingStars( - reinterpret_cast<ExtensionInstallUI::Prompt::StarAppender>( - AddResourceIcon), - stars_hbox); + prompt.AppendRatingStars(AddResourceIcon, stars_hbox); GtkWidget* rating_label = gtk_label_new(UTF16ToUTF8( prompt.GetRatingCount()).c_str()); gtk_util::ForceFontSizePixels(rating_label, kRatingTextSize); diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index 9e41a93..bb84b2a 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc @@ -49,9 +49,8 @@ const int kHeadingFontSizeDelta = 1; const int kRatingFontSizeDelta = -1; -void AddResourceIcon(int resource_id, views::View* parent) { - const SkBitmap* skia_image = ResourceBundle::GetSharedInstance(). - GetBitmapNamed(resource_id); +void AddResourceIcon(const SkBitmap* skia_image, void* data) { + views::View* parent = static_cast<views::View*>(data); views::ImageView* image_view = new views::ImageView(); image_view->SetImage(*skia_image); parent->AddChildView(image_view); @@ -195,10 +194,7 @@ ExtensionInstallDialogView::ExtensionInstallDialogView( rating->SetLayoutManager(new views::BoxLayout( views::BoxLayout::kHorizontal, 0, 0, 0)); layout->AddView(rating); - prompt.AppendRatingStars( - reinterpret_cast<ExtensionInstallUI::Prompt::StarAppender>( - AddResourceIcon), - rating); + prompt.AppendRatingStars(AddResourceIcon, rating); views::Label* rating_count = new views::Label( UTF16ToWide(prompt.GetRatingCount())); |