Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller. h" | 5 #import "chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller. h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | |
| 7 #include "base/i18n/rtl.h" | 8 #include "base/i18n/rtl.h" |
| 8 #include "base/mac/bundle_locations.h" | 9 #include "base/mac/bundle_locations.h" |
| 9 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
| 10 #include "base/memory/scoped_nsobject.h" | 11 #include "base/memory/scoped_nsobject.h" |
| 11 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 12 #include "base/sys_string_conversions.h" | 13 #include "base/sys_string_conversions.h" |
| 13 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 14 #include "chrome/browser/extensions/bundle_installer.h" | 15 #include "chrome/browser/extensions/bundle_installer.h" |
| 15 #include "chrome/browser/extensions/extension_install_dialog.h" | 16 #include "chrome/browser/extensions/extension_install_dialog.h" |
| 16 #include "chrome/common/extensions/extension.h" | 17 #include "chrome/common/extensions/extension.h" |
| 17 #include "content/public/browser/page_navigator.h" | 18 #include "content/public/browser/page_navigator.h" |
| 18 #include "grit/generated_resources.h" | 19 #include "grit/generated_resources.h" |
| 19 #include "skia/ext/skia_utils_mac.h" | 20 #include "skia/ext/skia_utils_mac.h" |
| 20 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" | 21 #import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h" |
| 21 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
| 22 #include "ui/base/l10n/l10n_util_mac.h" | 23 #include "ui/base/l10n/l10n_util_mac.h" |
| 23 | 24 |
| 24 using content::OpenURLParams; | 25 using content::OpenURLParams; |
| 25 using content::Referrer; | 26 using content::Referrer; |
| 26 using extensions::BundleInstaller; | 27 using extensions::BundleInstaller; |
| 27 | 28 |
| 28 @interface ExtensionInstallDialogController () | 29 @interface ExtensionInstallDialogController () |
| 29 - (BOOL)isBundleInstall; | 30 - (BOOL)isBundleInstall; |
| 30 - (BOOL)isInlineInstall; | 31 - (BOOL)isInlineInstall; |
| 31 - (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage; | 32 - (void)appendRatingStar:(const gfx::ImageSkia*)skiaImage; |
| 33 - (void)onOutlineViewRowCountDidChange; | |
| 32 @end | 34 @end |
| 33 | 35 |
| 34 namespace { | 36 namespace { |
| 35 | 37 |
| 36 // Padding above the warnings separator, we must also subtract this when hiding | 38 // Padding above the warnings separator, we must also subtract this when hiding |
| 37 // it. | 39 // it. |
| 38 const CGFloat kWarningsSeparatorPadding = 14; | 40 const CGFloat kWarningsSeparatorPadding = 14; |
| 39 | 41 |
| 40 // Maximum height we will adjust controls to when trying to accomodate their | 42 // Maximum height we will adjust controls to when trying to accomodate their |
| 41 // contents. | 43 // contents. |
| 42 const CGFloat kMaxControlHeight = 400; | 44 const CGFloat kMaxControlHeight = 400; |
| 43 | 45 |
| 46 NSString* const kTitleKey = @"title"; | |
| 47 NSString* const kIsGroupItemKey = @"isGroupItem"; | |
| 48 NSString* const kChildrenKey = @"children"; | |
| 49 NSString* const kCanExpandKey = @"canExpand"; | |
| 50 | |
| 44 // Adjust the |control|'s height so that its content is not clipped. | 51 // Adjust the |control|'s height so that its content is not clipped. |
| 45 // This also adds the change in height to the |totalOffset| and shifts the | 52 // This also adds the change in height to the |totalOffset| and shifts the |
| 46 // control down by that amount. | 53 // control down by that amount. |
| 47 void OffsetControlVerticallyToFitContent(NSControl* control, | 54 void OffsetControlVerticallyToFitContent(NSControl* control, |
| 48 CGFloat* totalOffset) { | 55 CGFloat* totalOffset) { |
| 49 // Adjust the control's height so that its content is not clipped. | 56 // Adjust the control's height so that its content is not clipped. |
| 50 NSRect currentRect = [control frame]; | 57 NSRect currentRect = [control frame]; |
| 51 NSRect fitRect = currentRect; | 58 NSRect fitRect = currentRect; |
| 52 fitRect.size.height = kMaxControlHeight; | 59 fitRect.size.height = kMaxControlHeight; |
| 53 CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height; | 60 CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height; |
| 54 CGFloat offset = desiredHeight - currentRect.size.height; | 61 CGFloat offset = desiredHeight - currentRect.size.height; |
| 55 | 62 |
| 56 [control setFrameSize:NSMakeSize(currentRect.size.width, | 63 [control setFrameSize:NSMakeSize(currentRect.size.width, |
| 57 currentRect.size.height + offset)]; | 64 currentRect.size.height + offset)]; |
| 58 | 65 |
| 59 *totalOffset += offset; | 66 *totalOffset += offset; |
| 60 | 67 |
| 61 // Move the control vertically by the new total offset. | 68 // Move the control vertically by the new total offset. |
| 62 NSPoint origin = [control frame].origin; | 69 NSPoint origin = [control frame].origin; |
| 63 origin.y -= *totalOffset; | 70 origin.y -= *totalOffset; |
| 64 [control setFrameOrigin:origin]; | 71 [control setFrameOrigin:origin]; |
| 65 } | 72 } |
| 66 | 73 |
| 74 // Gets the desired height of |outlineView|. Simply using the view's frame | |
| 75 // doesn't work if an animation is pending. | |
| 76 CGFloat GetDesiredOutlineViewHeight(NSOutlineView* outlineView) { | |
| 77 CGFloat height = 0; | |
| 78 for (NSInteger i = 0; i < [outlineView numberOfRows]; ++i) | |
| 79 height += [outlineView rectOfRow:i].size.height; | |
|
Robert Sesek
2012/08/06 21:31:48
nit: NSHeight
sail
2012/08/09 02:00:29
Done.
| |
| 80 return height; | |
| 81 } | |
| 82 | |
| 83 void OffsetOutlineViewVerticallyToFitContent(NSOutlineView* outlineView, | |
| 84 CGFloat* totalOffset) { | |
| 85 NSScrollView* scrollView = [outlineView enclosingScrollView]; | |
| 86 NSRect frame = [scrollView frame]; | |
| 87 CGFloat desiredHeight = GetDesiredOutlineViewHeight(outlineView); | |
| 88 CGFloat offset = desiredHeight - frame.size.height; | |
|
Robert Sesek
2012/08/06 21:31:48
nit: NSHeight
sail
2012/08/09 02:00:29
Done.
| |
| 89 frame.size.height += offset; | |
| 90 | |
| 91 *totalOffset += offset; | |
| 92 | |
| 93 // Move the control vertically by the new total offset. | |
| 94 frame.origin.y -= *totalOffset; | |
| 95 [scrollView setFrame:frame]; | |
| 96 } | |
| 97 | |
| 67 void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { | 98 void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { |
| 68 ExtensionInstallDialogController* controller = | 99 ExtensionInstallDialogController* controller = |
| 69 static_cast<ExtensionInstallDialogController*>(data); | 100 static_cast<ExtensionInstallDialogController*>(data); |
| 70 [controller appendRatingStar:skiaImage]; | 101 [controller appendRatingStar:skiaImage]; |
| 71 } | 102 } |
| 72 | 103 |
| 104 NSDictionary* BuildItem(NSString* title, BOOL isGroupItem, NSArray* children) { | |
|
Robert Sesek
2012/08/06 21:31:48
I think this may be easier to read inline as an Ob
sail
2012/08/09 02:00:29
Done.
| |
| 105 BOOL canExpand = YES; | |
| 106 if (!children) { | |
| 107 // Add a dummy child even though this is a leaf node. This will cause | |
| 108 // the outline view to show a disclosure triangle for this item. | |
| 109 // This is later overriden in willDisplayOutlineCell: to draw a bullet | |
| 110 // instead. (The bullet could be placed in the title instead but then | |
| 111 // the bullet wouldn't line up with disclosure triangles of sibling nodes.) | |
| 112 children = [NSArray arrayWithObject:[NSDictionary dictionary]]; | |
| 113 canExpand = false; | |
|
Robert Sesek
2012/08/06 21:31:48
NO
sail
2012/08/09 02:00:29
Done.
| |
| 114 } | |
| 115 | |
| 116 return [NSDictionary dictionaryWithObjectsAndKeys: | |
| 117 title, kTitleKey, | |
| 118 [NSNumber numberWithBool:isGroupItem], kIsGroupItemKey, | |
| 119 children, kChildrenKey, | |
| 120 [NSNumber numberWithBool:canExpand], kCanExpandKey, | |
| 121 nil]; | |
| 122 } | |
| 123 | |
| 124 NSDictionary* BuildIssue(const IssueAdviceInfoEntry& issue) { | |
| 125 if (issue.details.empty()) | |
| 126 return BuildItem(SysUTF16ToNSString(issue.description), NO, nil); | |
| 127 | |
| 128 NSMutableArray* details = [NSMutableArray array]; | |
| 129 for (size_t j = 0; j < issue.details.size(); ++j) { | |
| 130 [details addObject:BuildItem( | |
| 131 SysUTF16ToNSString(issue.details[j]), NO, nil)]; | |
| 132 } | |
| 133 return BuildItem(SysUTF16ToNSString(issue.description), NO, details); | |
| 134 } | |
| 135 | |
| 136 NSArray* BuildWarnings(const ExtensionInstallPrompt::Prompt& prompt) { | |
| 137 NSMutableArray* warnings = [NSMutableArray array]; | |
| 138 | |
| 139 if (prompt.GetPermissionCount() > 0) { | |
| 140 NSMutableArray* children = [NSMutableArray array]; | |
| 141 for (size_t i = 0; i < prompt.GetPermissionCount(); ++i) { | |
| 142 [children addObject:BuildItem( | |
| 143 SysUTF16ToNSString(prompt.GetPermission(i)), NO, nil)]; | |
| 144 } | |
| 145 [warnings addObject:BuildItem( | |
| 146 SysUTF16ToNSString(prompt.GetPermissionsHeading()), YES, children)]; | |
| 147 } | |
| 148 | |
| 149 if (prompt.GetOAuthIssueCount() > 0) { | |
| 150 NSMutableArray* children = [NSMutableArray array]; | |
| 151 for (size_t i = 0; i < prompt.GetOAuthIssueCount(); ++i) | |
| 152 [children addObject:BuildIssue(prompt.GetOAuthIssue(i))]; | |
| 153 [warnings addObject:BuildItem( | |
| 154 SysUTF16ToNSString(prompt.GetOAuthHeading()), YES, children)]; | |
| 155 } | |
| 156 | |
| 157 return warnings; | |
| 158 } | |
| 159 | |
| 160 void DrawBulletInFrame(NSRect frame) { | |
| 161 NSRect rect; | |
| 162 rect.size.width = std::min(frame.size.width, frame.size.height) * 0.38; | |
|
Robert Sesek
2012/08/06 21:31:48
Use NSWidth/Height in here
sail
2012/08/09 02:00:29
Done.
| |
| 163 rect.size.height = rect.size.width; | |
| 164 rect.origin.x = frame.origin.x + (frame.size.width - rect.size.width) / 2.0; | |
| 165 rect.origin.y = frame.origin.y + (frame.size.height - rect.size.height) / 2.0; | |
| 166 rect = NSIntegralRect(rect); | |
| 167 | |
| 168 [[NSColor colorWithCalibratedWhite:0.0 alpha:0.42] set]; | |
| 169 [[NSBezierPath bezierPathWithOvalInRect:rect] fill]; | |
| 170 } | |
| 171 | |
| 73 } | 172 } |
| 74 | 173 |
| 75 @implementation ExtensionInstallDialogController | 174 @implementation ExtensionInstallDialogController |
| 76 | 175 |
| 77 @synthesize iconView = iconView_; | 176 @synthesize iconView = iconView_; |
| 78 @synthesize titleField = titleField_; | 177 @synthesize titleField = titleField_; |
| 79 @synthesize itemsField = itemsField_; | 178 @synthesize itemsField = itemsField_; |
| 80 @synthesize subtitleField = subtitleField_; | |
| 81 @synthesize warningsField = warningsField_; | |
| 82 @synthesize cancelButton = cancelButton_; | 179 @synthesize cancelButton = cancelButton_; |
| 83 @synthesize okButton = okButton_; | 180 @synthesize okButton = okButton_; |
| 181 @synthesize outlineView = outlineView_; | |
| 84 @synthesize warningsSeparator = warningsSeparator_; | 182 @synthesize warningsSeparator = warningsSeparator_; |
| 85 @synthesize ratingStars = ratingStars_; | 183 @synthesize ratingStars = ratingStars_; |
| 86 @synthesize ratingCountField = ratingCountField_; | 184 @synthesize ratingCountField = ratingCountField_; |
| 87 @synthesize userCountField = userCountField_; | 185 @synthesize userCountField = userCountField_; |
| 88 | 186 |
| 89 - (id)initWithParentWindow:(NSWindow*)window | 187 - (id)initWithParentWindow:(NSWindow*)window |
| 90 navigator:(content::PageNavigator*)navigator | 188 navigator:(content::PageNavigator*)navigator |
| 91 delegate:(ExtensionInstallPrompt::Delegate*)delegate | 189 delegate:(ExtensionInstallPrompt::Delegate*)delegate |
| 92 prompt:(const ExtensionInstallPrompt::Prompt&)prompt { | 190 prompt:(const ExtensionInstallPrompt::Prompt&)prompt { |
| 93 NSString* nibpath = nil; | 191 NSString* nibpath = nil; |
| 192 warnings_.reset([BuildWarnings(prompt) retain]); | |
| 94 | 193 |
| 95 // We use a different XIB in the case of bundle installs, inline installs or | 194 // We use a different XIB in the case of bundle installs, inline installs or |
| 96 // no permission warnings. These are laid out nicely for the data they | 195 // no permission warnings. These are laid out nicely for the data they |
| 97 // display. | 196 // display. |
| 98 if (prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT) { | 197 if (prompt.type() == ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT) { |
| 99 nibpath = [base::mac::FrameworkBundle() | 198 nibpath = [base::mac::FrameworkBundle() |
| 100 pathForResource:@"ExtensionInstallPromptBundle" | 199 pathForResource:@"ExtensionInstallPromptBundle" |
| 101 ofType:@"nib"]; | 200 ofType:@"nib"]; |
| 102 } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) { | 201 } else if (prompt.type() == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT) { |
| 103 nibpath = [base::mac::FrameworkBundle() | 202 nibpath = [base::mac::FrameworkBundle() |
| 104 pathForResource:@"ExtensionInstallPromptInline" | 203 pathForResource:@"ExtensionInstallPromptInline" |
| 105 ofType:@"nib"]; | 204 ofType:@"nib"]; |
| 106 } else if (prompt.GetPermissionCount() == 0) { | 205 } else if (prompt.GetPermissionCount() == 0 && |
| 206 prompt.GetOAuthIssueCount() == 0) { | |
| 107 nibpath = [base::mac::FrameworkBundle() | 207 nibpath = [base::mac::FrameworkBundle() |
| 108 pathForResource:@"ExtensionInstallPromptNoWarnings" | 208 pathForResource:@"ExtensionInstallPromptNoWarnings" |
| 109 ofType:@"nib"]; | 209 ofType:@"nib"]; |
| 110 } else { | 210 } else { |
| 111 nibpath = [base::mac::FrameworkBundle() | 211 nibpath = [base::mac::FrameworkBundle() |
| 112 pathForResource:@"ExtensionInstallPrompt" | 212 pathForResource:@"ExtensionInstallPrompt" |
| 113 ofType:@"nib"]; | 213 ofType:@"nib"]; |
| 114 } | 214 } |
| 115 | 215 |
| 116 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { | 216 if ((self = [super initWithWindowNibPath:nibpath owner:self])) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], | 293 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], |
| 194 -buttonDelta.width, 0)]; | 294 -buttonDelta.width, 0)]; |
| 195 } | 295 } |
| 196 buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; | 296 buttonDelta = [GTMUILocalizerAndLayoutTweaker sizeToFitView:cancelButton_]; |
| 197 if (buttonDelta.width) { | 297 if (buttonDelta.width) { |
| 198 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], | 298 [cancelButton_ setFrame:NSOffsetRect([cancelButton_ frame], |
| 199 -buttonDelta.width, 0)]; | 299 -buttonDelta.width, 0)]; |
| 200 } | 300 } |
| 201 | 301 |
| 202 if ([self isBundleInstall]) { | 302 if ([self isBundleInstall]) { |
| 203 [subtitleField_ setStringValue:base::SysUTF16ToNSString( | |
| 204 prompt_->GetPermissionsHeading())]; | |
| 205 | |
| 206 // We display the list of extension names as a simple text string, seperated | 303 // We display the list of extension names as a simple text string, seperated |
| 207 // by newlines. | 304 // by newlines. |
| 208 BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState( | 305 BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState( |
| 209 BundleInstaller::Item::STATE_PENDING); | 306 BundleInstaller::Item::STATE_PENDING); |
| 210 | 307 |
| 211 NSMutableString* joinedItems = [NSMutableString string]; | 308 NSMutableString* joinedItems = [NSMutableString string]; |
| 212 for (size_t i = 0; i < items.size(); ++i) { | 309 for (size_t i = 0; i < items.size(); ++i) { |
| 213 if (i > 0) | 310 if (i > 0) |
| 214 [joinedItems appendString:@"\n"]; | 311 [joinedItems appendString:@"\n"]; |
| 215 [joinedItems appendString:base::SysUTF16ToNSString( | 312 [joinedItems appendString:base::SysUTF16ToNSString( |
| 216 items[i].GetNameForDisplay())]; | 313 items[i].GetNameForDisplay())]; |
| 217 } | 314 } |
| 218 [itemsField_ setStringValue:joinedItems]; | 315 [itemsField_ setStringValue:joinedItems]; |
| 219 | 316 |
| 220 // Adjust the controls to fit the list of extensions. | 317 // Adjust the controls to fit the list of extensions. |
| 221 OffsetControlVerticallyToFitContent(itemsField_, &totalOffset); | 318 OffsetControlVerticallyToFitContent(itemsField_, &totalOffset); |
| 222 } | 319 } |
| 223 | 320 |
| 224 // If there are any warnings, then we have to do some special layout. | 321 // If there are any warnings or OAuth issues, then we have to do some special |
| 225 if (prompt_->GetPermissionCount() > 0) { | 322 // layout. |
| 226 [subtitleField_ setStringValue:base::SysUTF16ToNSString( | 323 if (prompt_->GetPermissionCount() > 0 || prompt_->GetOAuthIssueCount() > 0) { |
| 227 prompt_->GetPermissionsHeading())]; | 324 NSSize spacing = [outlineView_ intercellSpacing]; |
| 228 | 325 spacing.width += 2; |
| 229 // We display the permission warnings as a simple text string, separated by | 326 spacing.height += 2; |
| 230 // newlines. | 327 [outlineView_ setIntercellSpacing:spacing]; |
| 231 NSMutableString* joinedWarnings = [NSMutableString string]; | 328 [[[[outlineView_ tableColumns] objectAtIndex:0] dataCell] setWraps:YES]; |
| 232 for (size_t i = 0; i < prompt_->GetPermissionCount(); ++i) { | 329 for (id item in warnings_.get()) { |
| 233 if (i > 0) | 330 if ([[item objectForKey:kIsGroupItemKey] boolValue]) |
| 234 [joinedWarnings appendString:@"\n"]; | 331 [outlineView_ expandItem:item expandChildren:NO]; |
| 235 [joinedWarnings appendString:base::SysUTF16ToNSString( | |
| 236 prompt_->GetPermission(i))]; | |
| 237 } | 332 } |
| 238 [warningsField_ setStringValue:joinedWarnings]; | 333 // Adjust the outline view to fit the warnings. |
| 239 | 334 OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset); |
| 240 // In the store version of the dialog the icon extends past the one-line | |
| 241 // version of the permission field. Therefore when increasing the window | |
| 242 // size for multi-line permissions we don't have to add the full offset, | |
| 243 // only the part that extends past the icon. | |
| 244 CGFloat warningsGrowthSlack = 0; | |
| 245 if (![self isBundleInstall] && | |
| 246 [warningsField_ frame].origin.y > [iconView_ frame].origin.y) { | |
| 247 warningsGrowthSlack = | |
| 248 [warningsField_ frame].origin.y - [iconView_ frame].origin.y; | |
| 249 } | |
| 250 | |
| 251 // Adjust the controls to fit the permission warnings. | |
| 252 OffsetControlVerticallyToFitContent(subtitleField_, &totalOffset); | |
| 253 OffsetControlVerticallyToFitContent(warningsField_, &totalOffset); | |
| 254 | |
| 255 totalOffset = MAX(totalOffset - warningsGrowthSlack, 0); | |
| 256 } else if ([self isInlineInstall] || [self isBundleInstall]) { | 335 } else if ([self isInlineInstall] || [self isBundleInstall]) { |
| 257 // Inline and bundle installs that don't have a permissions section need to | 336 // Inline and bundle installs that don't have a permissions section need to |
| 258 // hide controls related to that and shrink the window by the space they | 337 // hide controls related to that and shrink the window by the space they |
| 259 // take up. | 338 // take up. |
| 260 NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame], | 339 NSRect hiddenRect = NSUnionRect([warningsSeparator_ frame], |
| 261 [subtitleField_ frame]); | 340 [[outlineView_ enclosingScrollView] frame]); |
| 262 hiddenRect = NSUnionRect(hiddenRect, [warningsField_ frame]); | |
| 263 [warningsSeparator_ setHidden:YES]; | 341 [warningsSeparator_ setHidden:YES]; |
| 264 [subtitleField_ setHidden:YES]; | 342 [[outlineView_ enclosingScrollView] setHidden:YES]; |
| 265 [warningsField_ setHidden:YES]; | |
| 266 totalOffset -= hiddenRect.size.height + kWarningsSeparatorPadding; | 343 totalOffset -= hiddenRect.size.height + kWarningsSeparatorPadding; |
| 267 } | 344 } |
| 268 | 345 |
| 269 // If necessary, adjust the window size. | 346 // If necessary, adjust the window size. |
| 270 if (totalOffset) { | 347 if (totalOffset) { |
| 271 NSRect currentRect = [[self window] frame]; | 348 NSRect currentRect = [[self window] frame]; |
| 272 [[self window] setFrame:NSMakeRect(currentRect.origin.x, | 349 [[self window] setFrame:NSMakeRect(currentRect.origin.x, |
| 273 currentRect.origin.y - totalOffset, | 350 currentRect.origin.y - totalOffset, |
| 274 currentRect.size.width, | 351 currentRect.size.width, |
| 275 currentRect.size.height + totalOffset) | 352 currentRect.size.height + totalOffset) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 306 CGFloat maxStarRight = 0; | 383 CGFloat maxStarRight = 0; |
| 307 if ([[ratingStars_ subviews] count]) { | 384 if ([[ratingStars_ subviews] count]) { |
| 308 maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]); | 385 maxStarRight = NSMaxX([[[ratingStars_ subviews] lastObject] frame]); |
| 309 } | 386 } |
| 310 NSRect starBounds = NSMakeRect(maxStarRight, 0, | 387 NSRect starBounds = NSMakeRect(maxStarRight, 0, |
| 311 skiaImage->width(), skiaImage->height()); | 388 skiaImage->width(), skiaImage->height()); |
| 312 [view setFrame:starBounds]; | 389 [view setFrame:starBounds]; |
| 313 [ratingStars_ addSubview:view]; | 390 [ratingStars_ addSubview:view]; |
| 314 } | 391 } |
| 315 | 392 |
| 393 - (void)onOutlineViewRowCountDidChange { | |
| 394 // Force the outline view to update. | |
| 395 [outlineView_ reloadData]; | |
| 396 | |
| 397 CGFloat totalOffset = 0.0; | |
| 398 OffsetOutlineViewVerticallyToFitContent(outlineView_, &totalOffset); | |
| 399 if (totalOffset) { | |
| 400 NSRect currentRect = [[self window] frame]; | |
| 401 [[self window] setFrame:NSMakeRect(currentRect.origin.x, | |
|
Robert Sesek
2012/08/06 21:31:48
Why not just mutate currentRect and pass that?
sail
2012/08/09 02:00:29
Done.
Good idea.
| |
| 402 currentRect.origin.y - totalOffset, | |
| 403 currentRect.size.width, | |
| 404 currentRect.size.height + totalOffset) | |
| 405 display:YES]; | |
| 406 } | |
| 407 } | |
| 408 | |
| 409 - (id)outlineView:(NSOutlineView*)outlineView | |
| 410 child:(NSInteger)index | |
| 411 ofItem:(id)item { | |
| 412 if (!item) | |
| 413 return [warnings_ objectAtIndex:index]; | |
| 414 if ([item isKindOfClass:[NSDictionary class]]) | |
| 415 return [[item objectForKey:kChildrenKey] objectAtIndex:index]; | |
| 416 NOTREACHED(); | |
| 417 return nil; | |
| 418 } | |
| 419 | |
| 420 - (BOOL)outlineView:(NSOutlineView*)outlineView | |
| 421 isItemExpandable:(id)item { | |
| 422 return [self outlineView:outlineView numberOfChildrenOfItem:item] > 0; | |
| 423 } | |
| 424 | |
| 425 - (NSInteger)outlineView:(NSOutlineView*)outlineView | |
| 426 numberOfChildrenOfItem:(id)item { | |
| 427 if (!item) | |
| 428 return [warnings_ count]; | |
| 429 if ([item isKindOfClass:[NSDictionary class]]) | |
| 430 return [[item objectForKey:kChildrenKey] count]; | |
| 431 NOTREACHED(); | |
| 432 return 0; | |
| 433 } | |
| 434 | |
| 435 - (id)outlineView:(NSOutlineView*)outlineView | |
| 436 objectValueForTableColumn:(NSTableColumn *)tableColumn | |
| 437 byItem:(id)item { | |
| 438 return [item objectForKey:kTitleKey]; | |
| 439 } | |
| 440 | |
| 441 - (BOOL)outlineView:(NSOutlineView *)outlineView | |
| 442 shouldExpandItem:(id)item { | |
| 443 return [[item objectForKey:kCanExpandKey] boolValue]; | |
| 444 } | |
| 445 | |
| 446 - (void)outlineViewItemDidExpand:sender { | |
| 447 // Call via run loop to avoid animation glitches. | |
| 448 [self performSelector:@selector(onOutlineViewRowCountDidChange) | |
| 449 withObject:nil | |
| 450 afterDelay:0]; | |
| 451 } | |
| 452 | |
| 453 - (void)outlineViewItemDidCollapse:sender { | |
| 454 // Call via run loop to avoid animation glitches. | |
| 455 [self performSelector:@selector(onOutlineViewRowCountDidChange) | |
| 456 withObject:nil | |
| 457 afterDelay:0]; | |
| 458 } | |
| 459 | |
| 460 - (CGFloat)outlineView:(NSOutlineView *)outlineView | |
| 461 heightOfRowByItem:(id)item { | |
| 462 // Prevent reentrancy due to the frameOfCellAtColumn:row: call below. | |
| 463 if (isComputingRowHeight) | |
| 464 return 1; | |
| 465 AutoReset<BOOL> reset(&isComputingRowHeight, YES); | |
| 466 | |
| 467 NSCell* cell = [[[outlineView_ tableColumns] objectAtIndex:0] dataCell]; | |
| 468 [cell setStringValue:[item objectForKey:kTitleKey]]; | |
| 469 NSRect bounds = NSZeroRect; | |
| 470 NSInteger row = [outlineView_ rowForItem:item]; | |
| 471 bounds.size.width = [outlineView_ frameOfCellAtColumn:0 | |
| 472 row:row].size.width; | |
|
Robert Sesek
2012/08/06 21:31:48
NSWidth
sail
2012/08/09 02:00:29
Done.
| |
| 473 bounds.size.height = kMaxControlHeight; | |
| 474 | |
| 475 return [cell cellSizeForBounds:bounds].height; | |
| 476 } | |
| 477 | |
| 478 - (BOOL)outlineView:(NSOutlineView*)outlineView | |
| 479 shouldShowOutlineCellForItem:(id)item { | |
| 480 // The top most group header items are always expanded so hide their | |
| 481 // disclosure trianggles. | |
| 482 return ![[item objectForKey:kIsGroupItemKey] boolValue]; | |
| 483 } | |
| 484 | |
| 485 - (void)outlineView:(NSOutlineView*)outlineView | |
| 486 willDisplayCell:(id)cell | |
| 487 forTableColumn:(NSTableColumn *)tableColumn | |
| 488 item:(id)item { | |
| 489 if ([[item objectForKey:kIsGroupItemKey] boolValue]) | |
| 490 [cell setFont:[NSFont boldSystemFontOfSize:11.0]]; | |
| 491 else | |
| 492 [cell setFont:[NSFont systemFontOfSize:11.0]]; | |
| 493 } | |
| 494 | |
| 495 - (void)outlineView:(NSOutlineView *)outlineView | |
| 496 willDisplayOutlineCell:(id)cell | |
| 497 forTableColumn:(NSTableColumn *)tableColumn | |
| 498 item:(id)item { | |
| 499 // Replace disclosure triangles with bullet lists for leaf nodes. | |
| 500 if (![[item objectForKey:kCanExpandKey] boolValue]) { | |
| 501 [cell setImagePosition:NSNoImage]; | |
| 502 DrawBulletInFrame([outlineView_ frameOfOutlineCellAtRow: | |
| 503 [outlineView_ rowForItem:item]]); | |
| 504 } else { | |
| 505 // Reset image to default value. | |
| 506 [cell setImagePosition:NSImageOverlaps]; | |
| 507 } | |
| 508 } | |
| 509 | |
| 316 @end // ExtensionInstallDialogController | 510 @end // ExtensionInstallDialogController |
| 317 | 511 |
| 318 void ShowExtensionInstallDialogImpl( | 512 void ShowExtensionInstallDialogImpl( |
| 319 gfx::NativeWindow parent, | 513 gfx::NativeWindow parent, |
| 320 content::PageNavigator* navigator, | 514 content::PageNavigator* navigator, |
| 321 ExtensionInstallPrompt::Delegate* delegate, | 515 ExtensionInstallPrompt::Delegate* delegate, |
| 322 const ExtensionInstallPrompt::Prompt& prompt) { | 516 const ExtensionInstallPrompt::Prompt& prompt) { |
| 323 ExtensionInstallDialogController* controller = | 517 ExtensionInstallDialogController* controller = |
| 324 [[ExtensionInstallDialogController alloc] | 518 [[ExtensionInstallDialogController alloc] |
| 325 initWithParentWindow:parent | 519 initWithParentWindow:parent |
| 326 navigator:navigator | 520 navigator:navigator |
| 327 delegate:delegate | 521 delegate:delegate |
| 328 prompt:prompt]; | 522 prompt:prompt]; |
| 329 | 523 |
| 330 // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455) | 524 // TODO(mihaip): Switch this to be tab-modal (http://crbug.com/95455) |
| 331 [controller runAsModalSheet]; | 525 [controller runAsModalSheet]; |
| 332 } | 526 } |
| OLD | NEW |