Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Unified Diff: chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm

Issue 7835039: Implement the inline extensions/apps install UI for Cocoa. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm
===================================================================
--- chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm (revision 99418)
+++ chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm (working copy)
@@ -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,17 +56,26 @@
[control setFrameOrigin:origin];
}
+void AppendRatingStarsShim(const SkBitmap* skiaImage, void* data) {
+ ExtensionInstallDialogController* controller =
+ static_cast<ExtensionInstallDialogController*>(data);
+ [controller appendRatingStar:skiaImage];
}
+}
+
@implementation ExtensionInstallDialogController
@synthesize iconView = iconView_;
@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,10 +85,15 @@
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"];
} else {
@@ -82,32 +107,8 @@
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 @@
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)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 @@
[[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;
+ 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;
+ }
- NSRect warningsBoxRect = [warningsBox_ frame];
- warningsBoxRect.origin.y -= totalOffset;
- warningsBoxRect.size.height += warningsOffset;
- [warningsBox_ setFrame:warningsBoxRect];
-
- // buttons are positioned automatically in the XIB.
-
- // 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 @@
[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 @@
icon:icon
prompt:prompt];
+ // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455)
[controller runAsModalSheet];
}

Powered by Google App Engine
This is Rietveld 408576698