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

Side by Side Diff: chrome/browser/ui/cocoa/extensions/extension_install_dialog_controller.mm

Issue 10829170: Cocoa: Show OAuth issues in extension install dialog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use autoreset Created 8 years, 4 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698