|
|
Description[AiS] changing mac omnibox suggestions form NSMatrix to NSTableView
This initial change should look the same from the user's perspective.
BUG=449593
Committed: https://crrev.com/aa726aa5c1121fc55c9cf5b40e18ca1d0a9b7337
Cr-Commit-Position: refs/heads/master@{#334305}
Patch Set 1 #
Total comments: 43
Patch Set 2 : review changes #
Total comments: 39
Patch Set 3 : review changes, changed hover and selection tracking #Patch Set 4 : removed old code, fix for unit test #Patch Set 5 : fixes for mac unit tests; changed cpp delegate function names #Patch Set 6 : cl format changes #Patch Set 7 : Reworked AiS table view data source #Patch Set 8 : Removed unneeded code #
Total comments: 17
Patch Set 9 : fix for unit test #Patch Set 10 : Reduced cell redraw on hover #
Total comments: 15
Patch Set 11 : Review changes and rounding error fix #
Total comments: 40
Patch Set 12 : Int to float changes and cleanup some table overrides #Patch Set 13 : added comment about copy with zone #Patch Set 14 : Added popup cell data class #Patch Set 15 : unit test fix #
Total comments: 17
Patch Set 16 : Review changes #
Total comments: 45
Patch Set 17 : changed accessors for OmniboxPopupCellData #Patch Set 18 : Removed cell data rect #
Total comments: 36
Patch Set 19 : The role of the DataSource is more clear #Patch Set 20 : Removed withView arg from highlightRowAt #
Total comments: 101
Patch Set 21 : Review changes #Patch Set 22 : Merge from master #Patch Set 23 : Fix for interactive_ui_tests. #Patch Set 24 : Changed OmniboxPopupCellData to be in objectValue rather than representedObject #Patch Set 25 : Merge from master to fix unit test #Patch Set 26 : merging master; unit test fix #Patch Set 27 : moved description access to test code #
Total comments: 8
Patch Set 28 : Moved cell drawing code #Patch Set 29 : added NSCopying to fix unit test #Patch Set 30 : fix for browswer tests #Patch Set 31 : Merge form master #
Total comments: 41
Patch Set 32 : Review changes #Patch Set 33 : moved separator init #
Total comments: 40
Patch Set 34 : reveiw changes #Patch Set 35 : removed prefix centering #Patch Set 36 : Fix for unused var #
Total comments: 25
Patch Set 37 : Fixes for init of content offset #Patch Set 38 : Added member declarations #Patch Set 39 : review changes; comments; objc casts #Patch Set 40 : autorelease on column data cell #Messages
Total messages: 77 (6 generated)
dschuyler@chromium.org changed reviewers: + groby@chromium.org
Hi, I need to work on the unit tests for this CL, so it's not ready to commit yet. I'm hoping to get some initial feedback on this CL early from groby and shrike, so I'm sending it now. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:21: OmniboxPopupViewMac* parent_; This wasn't being used. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:28: const CGFloat kCellHeightAdjust = 6.0; This is moved from another file in this CL. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:215: NSAttributedString* prefix = prefix_.release(); This is my first shot at a copyWithZone member. I patterned this after other examples I found in chromium. I thought something like this should work, though it didn't seem to: copy->separator_.reset([separator_.get() copy]); https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: [self renewRows:0 columns:1]; The initial column is now added in a different function. So we still add the column, but for a TableView it needs to be done a different way. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:38: [self setMode:NSRadioModeMatrix]; There doesn't seem to be an equivalent for this concept in TableView, so just removing it seems the right thing to do. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:27: if (!array_) Checking whether the member is initialized comes from advice in the Apple docs. They caution that numberOfRowsInTableView may be called at unexpected times and that one should guard against this possibility in this call. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:208: return [controller_ setCellCount:count]; I'm torn on whether a wrapper call like this is good. What are your thoughts? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:213: if (row < 0 || row >= (NSInteger)[array count]) row == -1 does happen normally. The high guard is just for defensive programming, I haven't seen it happen. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h:49: OmniboxPopupMatrix* matrix() { return matrix_; } This wasn't being used. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:34: const CGFloat kCellHeightAdjust = 6.0; This moved to another file in this CL. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:101: DCHECK_GT(matrix_width, 0.0); This is moved elsewhere in this file in this CL. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:129: popupHeight += [table_view_ intercellSpacing].height * (rows - 1); This isn't strictly necessary. Right now the spacing is always zero. Though this will be needed in the spacing is changed (and maybe it should be instead of using kCellHeightAdjust to alter the frame by hand). https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:244: // return; This short circuit causes a problem with the highlight background widths. I thought about just removing it, but it's still here while I re-think whether there is merit in converting this to work with the TableView. What are your thoughts on it? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:273: DCHECK_GT(tableWidth, 0.0); This is moved here from elsewhere in the code, in this CL.
Just a quick scan... https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:21: OmniboxPopupViewMac* parent_; On 2015/04/24 18:43:08, dschuyler wrote: > This wasn't being used. If it's not used in existing code, might as well submit a separate cleanup CL. It's useful independent of where this goes. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:213: NSAttributedString* separator = separator_.release(); Why release them? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:215: NSAttributedString* prefix = prefix_.release(); On 2015/04/24 18:43:08, dschuyler wrote: > This is my first shot at a copyWithZone member. I patterned this after other > examples I found in chromium. > I thought something like this should work, though it didn't seem to: > copy->separator_.reset([separator_.get() copy]); Why does this not work? Also, copy->separator_reset([separator_ copy]); // no get needed. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:27: if (!array_) On 2015/04/24 18:43:08, dschuyler wrote: > Checking whether the member is initialized comes from advice in the Apple docs. > They caution that numberOfRowsInTableView may be called at unexpected times and > that one should guard against this possibility in this call. I'm confused. If the member is not initialized, this becomes [nil count], which automatically evaluates to 0. Do you have a link/quote? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: [array_ addObject:[[OmniboxPopupCell alloc] init]]; This leaks. (addObject retains, alloc retains) https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: while (count < (NSInteger)[array_ count]) { Why the cast? Also, why not if (count < [array_ count]) { [array_ removeObjectsInRange:NSMakeRange(count,[array_ count]-1)]; https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:56: // Setup defaults. That comment is rather meaningless - what defaults? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:208: return [controller_ setCellCount:count]; On 2015/04/24 18:43:08, dschuyler wrote: > I'm torn on whether a wrapper call like this is good. What are your thoughts? It is :) (Long-form argument at http://en.wikipedia.org/wiki/Law_of_Demeter & https://pragprog.com/articles/tell-dont-ask) https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:213: if (row < 0 || row >= (NSInteger)[array count]) On 2015/04/24 18:43:08, dschuyler wrote: > row == -1 does happen normally. The high guard is just for defensive > programming, I haven't seen it happen. That kind of screams for an NSUInteger https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:236: OmniboxPopupCell* highlightCell = [self cellAtRow:rowIndex]; Why check that here? Why not just tell the controller to highlight a cell? Also, why not just remember which cell the highlightcell is, as opposed to scanning everything all the time? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:244: // return; On 2015/04/24 18:43:09, dschuyler wrote: > This short circuit causes a problem with the highlight background widths. I > thought about just removing it, but it's still here while I re-think whether > there is merit in converting this to work with the TableView. What are your > thoughts on it? I'm not sure what exactly this does, or why removing it is helpful, so it's hard to make that call :)
rsesek@chromium.org changed reviewers: + shess@chromium.org
shess@ should be at least CC'd on all Mac Omnibox reviews (unless he doesn't want to be :)
https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:213: NSAttributedString* separator = separator_.release(); On 2015/04/24 20:11:16, groby wrote: > Why release them? I was using code from this file as a pattern: src/ui/base/cocoa/controls/hyperlink_button_cell.mm I was getting a crash in this code and looked for a how it was done elsewhere. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:215: NSAttributedString* prefix = prefix_.release(); On 2015/04/24 20:11:16, groby wrote: > On 2015/04/24 18:43:08, dschuyler wrote: > > This is my first shot at a copyWithZone member. I patterned this after other > > examples I found in chromium. > > I thought something like this should work, though it didn't seem to: > > copy->separator_.reset([separator_.get() copy]); > > Why does this not work? Also, copy->separator_reset([separator_ copy]); // no > get needed. I must have mislead myself. I was getting a crash (segfault iirc) in this code, so I changed it to pattern after some existing code (that did a release). Changing back to the way I wanted it (as you suggest) seems fine now. There likely was an unrelated issue that I fixed separately and didn't realize that it would fix this. I'm changing to the other way of doing the copy. Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:27: if (!array_) On 2015/04/24 20:11:16, groby wrote: > On 2015/04/24 18:43:08, dschuyler wrote: > > Checking whether the member is initialized comes from advice in the Apple > docs. > > They caution that numberOfRowsInTableView may be called at unexpected times > and > > that one should guard against this possibility in this call. > > I'm confused. If the member is not initialized, this becomes [nil count], which > automatically evaluates to 0. Do you have a link/quote? Ah, so I was trying to do right by the 'Important' call out on this page. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Applica... Your comment explains that 'if' is not necessary - the code will still satisfy the call out on that page. Thanks! Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: [array_ addObject:[[OmniboxPopupCell alloc] init]]; On 2015/04/24 20:11:16, groby wrote: > This leaks. (addObject retains, alloc retains) Is autorelease the right thing to do here? Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: while (count < (NSInteger)[array_ count]) { On 2015/04/24 20:11:16, groby wrote: > Why the cast? It's a compile error to compare signed and unsigned ints. It was signed because the api seemed to use signed values (even where I would lean toward unsigned values). I've changed the parameter to unsigned and removed the casts. > > Also, why not > if (count < [array_ count]) { > [array_ removeObjectsInRange:NSMakeRange(count,[array_ count]-1)]; I'm too new to Cocoa to know about removeObjectsInRange and NSMakeRange. And because that throws an out of range exception :) (the -1 should be -count). Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:56: // Setup defaults. On 2015/04/24 20:11:16, groby wrote: > That comment is rather meaningless - what defaults? Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:208: return [controller_ setCellCount:count]; On 2015/04/24 20:11:17, groby wrote: > On 2015/04/24 18:43:08, dschuyler wrote: > > I'm torn on whether a wrapper call like this is good. What are your thoughts? > > It is :) (Long-form argument at http://en.wikipedia.org/wiki/Law_of_Demeter & > https://pragprog.com/articles/tell-dont-ask) Acknowledged. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:213: if (row < 0 || row >= (NSInteger)[array count]) On 2015/04/24 20:11:17, groby wrote: > On 2015/04/24 18:43:08, dschuyler wrote: > > row == -1 does happen normally. The high guard is just for defensive > > programming, I haven't seen it happen. > > That kind of screams for an NSUInteger I heard that screaming as well, though I thought I was doing the right thing by doing what I saw other code doing (signed as an array index). Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:236: OmniboxPopupCell* highlightCell = [self cellAtRow:rowIndex]; On 2015/04/24 20:11:16, groby wrote: > Why check that here? Why not just tell the controller to highlight a cell? > > Also, why not just remember which cell the highlightcell is, as opposed to > scanning everything all the time? It comes from a presumption that the prior Googler that setup the code that way had valid reasons. The same thoughts occurred to me, but I wanted to get this working prior to diverging too far. I added the 'if' partly because of the thought: why are we looping over all the cells every time this is called - well, I can at least early out if it's not changing. Would this be something I should revisit after this CL?
https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:213: NSAttributedString* separator = separator_.release(); On 2015/04/25 01:05:42, dschuyler wrote: > On 2015/04/24 20:11:16, groby wrote: > > Why release them? > > I was using code from this file as a pattern: > src/ui/base/cocoa/controls/hyperlink_button_cell.mm > I was getting a crash in this code and looked for a how it was done elsewhere. Huh? HyperlinkButtonCell's -copyWithZone: does not release? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:215: NSAttributedString* prefix = prefix_.release(); On 2015/04/25 01:05:42, dschuyler wrote: > On 2015/04/24 20:11:16, groby wrote: > > On 2015/04/24 18:43:08, dschuyler wrote: > > > This is my first shot at a copyWithZone member. I patterned this after > other > > > examples I found in chromium. > > > I thought something like this should work, though it didn't seem to: > > > copy->separator_.reset([separator_.get() copy]); > > > > Why does this not work? Also, copy->separator_reset([separator_ copy]); // no > > get needed. > > I must have mislead myself. I was getting a crash (segfault iirc) in this code, > so I changed it to pattern after some existing code (that did a release). > Changing back to the way I wanted it (as you suggest) seems fine now. There > likely was an unrelated issue that I fixed separately and didn't realize that it > would fix this. I'm changing to the other way of doing the copy. > Done. I know it's tempting, but please don't cargo-cult around alloc/retain - we'll all pay for that :) https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: [array_ addObject:[[OmniboxPopupCell alloc] init]]; On 2015/04/25 01:05:43, dschuyler wrote: > On 2015/04/24 20:11:16, groby wrote: > > This leaks. (addObject retains, alloc retains) > > Is autorelease the right thing to do here? > > Done. Yes, it is :) Normal pattern for classes is to have a class method that returns an autoreleased object. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: while (count < (NSInteger)[array_ count]) { On 2015/04/25 01:05:43, dschuyler wrote: > On 2015/04/24 20:11:16, groby wrote: > > Why the cast? > It's a compile error to compare signed and unsigned ints. It was signed because > the api seemed to use signed values (even where I would lean toward unsigned > values). I've changed the parameter to unsigned and removed the casts. Excellent. Also, when you cast: Please always use static_cast<> and friends, not c-style casts (http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Casting) > > > > > Also, why not > > if (count < [array_ count]) { > > [array_ removeObjectsInRange:NSMakeRange(count,[array_ count]-1)]; > I'm too new to Cocoa to know about removeObjectsInRange and NSMakeRange. And > because that throws an out of range exception :) (the -1 should be -count). > > Done. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:213: if (row < 0 || row >= (NSInteger)[array count]) On 2015/04/25 01:05:43, dschuyler wrote: > On 2015/04/24 20:11:17, groby wrote: > > On 2015/04/24 18:43:08, dschuyler wrote: > > > row == -1 does happen normally. The high guard is just for defensive > > > programming, I haven't seen it happen. > > > > That kind of screams for an NSUInteger > > I heard that screaming as well, though I thought I was doing the right thing by > doing what I saw other code doing (signed as an array index). > > Done. Sigh. It's my old habits. We actually *shouldn't* use unsigned. Styleguide explicitly says no. (Use a DCHECK to assert sane ranges, if you must) https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:236: OmniboxPopupCell* highlightCell = [self cellAtRow:rowIndex]; On 2015/04/25 01:05:43, dschuyler wrote: > On 2015/04/24 20:11:16, groby wrote: > > Why check that here? Why not just tell the controller to highlight a cell? > > > > Also, why not just remember which cell the highlightcell is, as opposed to > > scanning everything all the time? > > It comes from a presumption that the prior Googler that setup the code that way > had valid reasons. The same thoughts occurred to me, but I wanted to get this > working prior to diverging too far. > > I added the 'if' partly because of the thought: why are we looping over all the > cells every time this is called - well, I can at least early out if it's not > changing. > > Would this be something I should revisit after this CL? Yeah, probably. I'd ping the Googler in Question (GIQ? ;) why this is.
On 2015/04/24 23:20:57, Robert Sesek (OOO 24.4-11.5) wrote: > shess@ should be at least CC'd on all Mac Omnibox reviews (unless he doesn't > want to be :) rsesek is my new (anti-)hero! I can review it, but I'm no longer able to channel the person who wrote it, so it's entirely plausible that I'll miss obvious whoppers. I'm kind of surprised that it works with the NSMatrix-centric methods overriding in an NSTableView context. The things I'd poke at would be how highlight changes as you hover while moving the cursor across the intercell spacing, and also into the padding around the view, and also as you move the cursor off-window. Off-and-back-on is also sometimes interesting. Then similar for selection as you drag. I'm less concerned about keyboard selection as that wasn't really a big problem with the matrix version. Your CL description should be a comment used to communicate to people living in the future who very much don't want to actually review the entire CL. So it should tell what your CL is _doing_, not what future feature it is preparing for. Pretend you're reviewing the last 500 CLs for which one introduced a regression into the omnibox popup view, and consider whether that person will have any idea what "Answers in Suggest" means. Also NXMatrix -> NSMatrix. Also you presumably have a bug for tracking implementation of the overall feature on OSX? https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (left): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:21: OmniboxPopupViewMac* parent_; On 2015/04/24 20:11:16, groby wrote: > On 2015/04/24 18:43:08, dschuyler wrote: > > This wasn't being used. > > If it's not used in existing code, might as well submit a separate cleanup CL. > It's useful independent of where this goes. I support this message. Also, I notice that a lot of the overall CL are s/matrix/table/ type changes. I wonder if it would make sense to instead just have this own the abstraction and not export the implementation details. Like it could be OmniboxPopupControl or something (even if it later becomes a full-on custom implementation, it seems likely to still be an NSControl subclass). https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:18: @interface OmniboxPopupCell : NSButtonCell<NSCopying> { NSButtonCell already conforms to NSCopying. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:18: NSMutableArray* array_; Should this be a scoped_nsobject<NSMutableArray>? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:50: OmniboxPopupTableController* controller_; scoped_nsobject<>? Someone needs to own it. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:57: - (void)setCppDelegate:(OmniboxPopupTableDelegate*)delegate; I think that's a reasonable change, if clunky (but C++ plus Objective-C can be clunky), but if you make it you should be comprehensive about it. -initWithCppDelegate, cpp_delegate, etc. Or figure out an alternative phrasing, though that is prone to being even weirder when someone else starts using it on either side of the divide. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:67: - (OmniboxPopupCell*)cellAtRow:(NSUInteger)row; I can see why you did this for convenience sake, but generally Cocoa code expects the caller to check limits. The omnibox_popup_view_mac.mm code which calls this really should fail hard if it passes an invalid row, so maybe just fix the -highlightRowAt: code to make the check. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:46: while (count >= [array_ count]) { Suggest while ([array_ count] < count)... Might be just me, but I find >= and <= to be signals for "Go back and review this code a couple times, because it's probably incorrect." Also, I might be confused, but I figured you defined the cell copy code to allow NSTableView to populate things, but here you're creating fresh cells and returning them above. So does the copy code ever actually kick into action? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:51: [array_ removeObjectsInRange:NSMakeRange(count, [array_ count] - count)]; This is documented as using -removeObjectsAtIndex: as the implementation. I wonder if it's smart relative to what you'd get with repeated application of -removeLastObject. It _probably_ is. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:55: [[array_ objectAtIndex:0] setState:NSOnState]; Since you may have re-used existing cells in array_, how do you know no other cells have NSOnState set? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:59: return array_; You document this as an immutable copy, but it can change after you return it if the caller makes calls which change array_. Consider [[array_ copy] autorelease]. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: NSTableColumn* column = scoped_nsobject<>. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:232: // highlighted. I think the out-of-range at this point is if the mouse is in the padding above or below the view. I don't recall the exact details, I think at one time this view acted as the backing for the popup window, but now I think there may be a superview doing that job, in which case it may no longer be possible to be above or below the valid rows. In any case, the use of -cellAtRow:column: wasn't because that's right, but because that worked, so I don't think you need to emulate that here for any particular reason. Also, I think the comment is out-of-place now. It looks to me like it applies to the if() just below, but really it applies to the if() in the for() loop. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:237: for (OmniboxPopupCell* cell in controller_.getCellArray) { I have no particular preference WRT controller_.getCellArray (well, I do, but my preference is ancient), but this code generally uses [controller_ getCellArray] style, so I think stick with that. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:240: } I'm not really sure what this is saying. The previous code set the highlight state of all the cells, exactly one of them would get true, the rest false. I think this maybe un-highlights the one which is highlighted, and highlights the one which is not? I think something like this would be clearer: if (cell == highlightCell) { [cell highlight:YES ...]; } else if ([cell isHighlighted]) { [cell highlight:NO ...]; } That said, the internal implementation of -highlight:* should short-circuit if the highlight state is the same, which means that calling -isHighlighted to check whether it is highlighted is approximately the same cost as just calling -highlight:* in the first place. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:74: setState:(line == model_->selected_line() ? NSOnState : NSOffState)]; Does this invalidate if that line is already set to that state? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:106: for (size_t ii = 0; ii < rows; ++ii) { |ii|? Criminy, when did I write this? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:244: // return; Pretty sure this was here for a reason. Unfortunately I don't know what that reason was any longer. I'd verify that there aren't edge cases like re-positioning while the animation is still running causing the animation to restart or something. Maybe there are old bugs to consult.
https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:59: return array_; On 2015/04/25 06:04:27, Scott Hess wrote: > You document this as an immutable copy, but it can change after you return it if > the caller makes calls which change array_. Consider [[array_ copy] > autorelease]. Technically, if the controller managed highlight/returning cell for a row, we don't need to expose the array at all. I'm all in favor of hiding implementation details :) https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:240: } On 2015/04/25 06:04:27, Scott Hess wrote: > I'm not really sure what this is saying. The previous code set the highlight > state of all the cells, exactly one of them would get true, the rest false. I > think this maybe un-highlights the one which is highlighted, and highlights the > one which is not? I think something like this would be clearer: > > if (cell == highlightCell) { > [cell highlight:YES ...]; > } else if ([cell isHighlighted]) { > [cell highlight:NO ...]; > } > > That said, the internal implementation of -highlight:* should short-circuit if > the highlight state is the same, which means that calling -isHighlighted to > check whether it is highlighted is approximately the same cost as just calling > -highlight:* in the first place. I'll re-ask the question I asked in my last comments: Is there a particular reason the code doesn't just track the currently highlighted cell? Why always iterate over everything? Am I missing a Cocoa subtlety here? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:244: // return; On 2015/04/25 06:04:28, Scott Hess wrote: > Pretty sure this was here for a reason. Unfortunately I don't know what that > reason was any longer. I'd verify that there aren't edge cases like > re-positioning while the animation is still running causing the animation to > restart or something. Maybe there are old bugs to consult. It's Saturday, I was bored, git blame smiled alluringly... There's no bug to consult. The CL is https://codereview.chromium.org/2010002/ The animation code seems to have changed significantly since then, so I'd recommend trying if this affects the repro case mentioned in that CL.
shrike@chromium.org changed reviewers: + shrike@chromium.org
Aside from other reviewer comments, LGTM. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:224: // Enlarge the cell size. Do you mean decrease the cell size?
Hi, This has been reworked quite a bit. Thanks to all three of you for the feedback/help. This version makes the data source store the data rather than the cells themselves. This patch also minimizes the unnecessary changes which can be done in separate CLs. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: [array_ addObject:[[OmniboxPopupCell alloc] init]]; On 2015/04/25 01:31:11, groby wrote: > On 2015/04/25 01:05:43, dschuyler wrote: > > On 2015/04/24 20:11:16, groby wrote: > > > This leaks. (addObject retains, alloc retains) > > > > Is autorelease the right thing to do here? > > > > Done. > > Yes, it is :) > > Normal pattern for classes is to have a class method that returns an > autoreleased object. Acknowledged. https://codereview.chromium.org/1099403005/diff/1/chrome/browser/ui/cocoa/omn... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: while (count < (NSInteger)[array_ count]) { On 2015/04/25 01:31:11, groby wrote: > On 2015/04/25 01:05:43, dschuyler wrote: > > On 2015/04/24 20:11:16, groby wrote: > > > Why the cast? > > It's a compile error to compare signed and unsigned ints. It was signed > because > > the api seemed to use signed values (even where I would lean toward unsigned > > values). I've changed the parameter to unsigned and removed the casts. > > Excellent. Also, when you cast: Please always use static_cast<> and friends, not > c-style casts > (http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Casting) > > > > > > > > > Also, why not > > > if (count < [array_ count]) { > > > [array_ removeObjectsInRange:NSMakeRange(count,[array_ count]-1)]; > > I'm too new to Cocoa to know about removeObjectsInRange and NSMakeRange. And > > because that throws an out of range exception :) (the -1 should be -count). > > > > Done. > Acknowledged. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:18: @interface OmniboxPopupCell : NSButtonCell<NSCopying> { On 2015/04/25 06:04:27, Scott Hess wrote: > NSButtonCell already conforms to NSCopying. Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:224: // Enlarge the cell size. On 2015/04/27 18:30:10, shrike wrote: > Do you mean decrease the cell size? Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:18: NSMutableArray* array_; On 2015/04/25 06:04:27, Scott Hess wrote: > Should this be a scoped_nsobject<NSMutableArray>? Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:50: OmniboxPopupTableController* controller_; On 2015/04/25 06:04:27, Scott Hess wrote: > scoped_nsobject<>? Someone needs to own it. Would the super own it with the setDelegate or setDataSource? Would it hurt to to scope it to this derived class even if the super does so as well? Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:57: - (void)setCppDelegate:(OmniboxPopupTableDelegate*)delegate; On 2015/04/25 06:04:27, Scott Hess wrote: > I think that's a reasonable change, if clunky (but C++ plus Objective-C can be > clunky), but if you make it you should be comprehensive about it. > -initWithCppDelegate, cpp_delegate, etc. Or figure out an alternative phrasing, > though that is prone to being even weirder when someone else starts using it on > either side of the divide. Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:67: - (OmniboxPopupCell*)cellAtRow:(NSUInteger)row; On 2015/04/25 06:04:27, Scott Hess wrote: > I can see why you did this for convenience sake, but generally Cocoa code > expects the caller to check limits. The omnibox_popup_view_mac.mm code which > calls this really should fail hard if it passes an invalid row, so maybe just > fix the -highlightRowAt: code to make the check. Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:46: while (count >= [array_ count]) { On 2015/04/25 06:04:27, Scott Hess wrote: > Suggest while ([array_ count] < count)... Might be just me, but I find >= and > <= to be signals for "Go back and review this code a couple times, because it's > probably incorrect." > > Also, I might be confused, but I figured you defined the cell copy code to allow > NSTableView to populate things, but here you're creating fresh cells and > returning them above. So does the copy code ever actually kick into action? I'm sure that in previous test I've done, it was being called. Even though I'm not seeing it called today, it seems correct to implement copyWithZone. Would it be better without the copyWithZone? Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:51: [array_ removeObjectsInRange:NSMakeRange(count, [array_ count] - count)]; On 2015/04/25 06:04:27, Scott Hess wrote: > This is documented as using -removeObjectsAtIndex: as the implementation. I > wonder if it's smart relative to what you'd get with repeated application of > -removeLastObject. It _probably_ is. Previously in this CL, it was calling removeLastObject. Should I consider changing it back or should I leave it as is? https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:55: [[array_ objectAtIndex:0] setState:NSOnState]; On 2015/04/25 06:04:27, Scott Hess wrote: > Since you may have re-used existing cells in array_, how do you know no other > cells have NSOnState set? Good catch. Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:59: return array_; On 2015/04/25 19:01:12, groby wrote: > On 2015/04/25 06:04:27, Scott Hess wrote: > > You document this as an immutable copy, but it can change after you return it > if > > the caller makes calls which change array_. Consider [[array_ copy] > > autorelease]. > > Technically, if the controller managed highlight/returning cell for a row, we > don't need to expose the array at all. I'm all in favor of hiding implementation > details :) Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:59: return array_; On 2015/04/25 06:04:27, Scott Hess wrote: > You document this as an immutable copy, but it can change after you return it if > the caller makes calls which change array_. Consider [[array_ copy] > autorelease]. That comment was odd - the array itself would not change, though the contents would. (Some math books would say the array would not 'change shape'). As Groby points out, it's reasonable to simply remove that function and its comment :) https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: NSTableColumn* column = On 2015/04/25 06:04:27, Scott Hess wrote: > scoped_nsobject<>. Could I have done autorelease here instead of the scoped_nsobject? Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:232: // highlighted. On 2015/04/25 06:04:27, Scott Hess wrote: > I think the out-of-range at this point is if the mouse is in the padding above > or below the view. I don't recall the exact details, I think at one time this > view acted as the backing for the popup window, but now I think there may be a > superview doing that job, in which case it may no longer be possible to be above > or below the valid rows. In any case, the use of -cellAtRow:column: wasn't > because that's right, but because that worked, so I don't think you need to > emulate that here for any particular reason. > > Also, I think the comment is out-of-place now. It looks to me like it applies > to the if() just below, but really it applies to the if() in the for() loop. This code has been reworked in the new patch. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:240: } On 2015/04/25 06:04:27, Scott Hess wrote: > I'm not really sure what this is saying. The previous code set the highlight > state of all the cells, exactly one of them would get true, the rest false. I > think this maybe un-highlights the one which is highlighted, and highlights the > one which is not? I think something like this would be clearer: > > if (cell == highlightCell) { > [cell highlight:YES ...]; > } else if ([cell isHighlighted]) { > [cell highlight:NO ...]; > } > > That said, the internal implementation of -highlight:* should short-circuit if > the highlight state is the same, which means that calling -isHighlighted to > check whether it is highlighted is approximately the same cost as just calling > -highlight:* in the first place. Done. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:240: } On 2015/04/25 19:01:12, groby wrote: > On 2015/04/25 06:04:27, Scott Hess wrote: > > I'm not really sure what this is saying. The previous code set the highlight > > state of all the cells, exactly one of them would get true, the rest false. I > > think this maybe un-highlights the one which is highlighted, and highlights > the > > one which is not? I think something like this would be clearer: > > > > if (cell == highlightCell) { > > [cell highlight:YES ...]; > > } else if ([cell isHighlighted]) { > > [cell highlight:NO ...]; > > } > > > > That said, the internal implementation of -highlight:* should short-circuit if > > the highlight state is the same, which means that calling -isHighlighted to > > check whether it is highlighted is approximately the same cost as just calling > > -highlight:* in the first place. > > I'll re-ask the question I asked in my last comments: Is there a particular > reason the code doesn't just track the currently highlighted cell? Why always > iterate over everything? Am I missing a Cocoa subtlety here? This code has been reworked in the new patch. It seems to work with tracking the values independently so far. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:74: setState:(line == model_->selected_line() ? NSOnState : NSOffState)]; On 2015/04/25 06:04:28, Scott Hess wrote: > Does this invalidate if that line is already set to that state? Not that I'm aware of. In my testing it is called twice per line change (once for the old line and once for the new line.
I am feeling a little wobbly on the NSTableView specifics going on, here, like I need to write an example and experiment around some corners. So if someone wants to either buttress or decimate my points, go for it. https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:50: OmniboxPopupTableController* controller_; On 2015/05/01 21:50:53, dschuyler wrote: > On 2015/04/25 06:04:27, Scott Hess wrote: > > scoped_nsobject<>? Someone needs to own it. > > Would the super own it with the setDelegate or setDataSource? Would it hurt to > to scope it to this derived class even if the super does so as well? > > Done. Usually, delegates are not owned pointers. I believe -setDataSource: also does not take ownership. Even if they did, the code in your designated -init was creating a strong reference and never releasing it, so someone needs to take long-term ownership of that reference (or you could delete it, but in this case I think that would just lead to use-after-free). https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:51: [array_ removeObjectsInRange:NSMakeRange(count, [array_ count] - count)]; On 2015/05/01 21:50:54, dschuyler wrote: > On 2015/04/25 06:04:27, Scott Hess wrote: > > This is documented as using -removeObjectsAtIndex: as the implementation. I > > wonder if it's smart relative to what you'd get with repeated application of > > -removeLastObject. It _probably_ is. > > Previously in this CL, it was calling removeLastObject. Should I consider > changing it back or should I leave it as is? I'm mixed. Rachel suggested that change, and I can see why, but until I noticed she had suggested that I was going to suggest: while (count < [array_ count]) { [array_ removeLastObject]; } because it reads simpler. And now I'm thinking "NSArray is annoying" followed closely by "I wonder if std::vector<scoped_nsobject<>> works like I think it would?" I suggest you leave it as-is and ignore me :-). https://codereview.chromium.org/1099403005/diff/20001/chrome/browser/ui/cocoa... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: NSTableColumn* column = On 2015/05/01 21:50:54, dschuyler wrote: > On 2015/04/25 06:04:27, Scott Hess wrote: > > scoped_nsobject<>. > > Could I have done autorelease here instead of the scoped_nsobject? scoped_nsobject<> means "Add a reference here, drop the reference when going out of scope." -autorelease means "Add this reference to a structure somewhere on the stack, which will be cleaned up in the future." Apple has done a ton to make -autorelease efficient, so performance-wise it's not super compelling, but having the object released in the scope of use rather than after the code in question runs is almost always a benefit, because if something goes wrong it's much easier to backtrack to the initiating code. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:221: } WRT your other question about whether -copyWithZone: is correct to implement, technically it sure is, but practically it seldom is unless you're implementing more at an infrastructure layer. For instance, you might copy over background color and highlight mode, because all cells in the control will share it. But I can't think of a case where you'd want to share match or description info between cells. That's the general case. The specific case of NSTableView is that it sometimes copies cells around internally, so for NSTableView cells using -tableView:dataCellForTableColumn:row: style, I think you're supposed to implement it. But you're using -tableView:willDisplayCell:forTableColumn:row:, which I think just re-uses the same cell over and over. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:19: NSInteger hovered_cell_; hovered_index_ or hovered_row_, since it's not the actual cell. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return [array_ objectAtIndex:rowIndex]; This isn't a cell, though, it's a dictionary. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:39: willDisplayCell:(id)aCell You should use ObjCCast<> or ObjCCastStrict<> to make this something more specific than id before otherwise messaging it. One is "Give me one of these or nil", the other is "Give me one of these or die", probably the latter is in order here. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:48: [aCell setMatch:acm->match_]; Since you manufacture the various internal info in -setMatch:, I don't think setting all that information on every display is necessarily great. I'd definitely drop a LOG(ERROR) somewhere and track how often more-expensive things are being called when you do things like hover around. You might also want to find someone else to rope in who is more current on NSTableView. It's possible my memories of which cases want to cache a bunch of cells versus which cases want to just re-build the cell on the fly are wrong. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:110: - (void)setTheDelegate:(OmniboxPopupMatrixDelegate*)delegate { WRT our discussing in the CL, I worry that -setTheDelegate: is even worse than -setCppDelegate:. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:44: [[AutocompleteMatchWrapper alloc] autorelease]; This object has been allocated but not initialized, you need an -init* of some sort between +alloc and -autorelease. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:106: [[AutocompleteMatchWrapper alloc] autorelease]; -init in here, too.
https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:221: } On 2015/05/04 19:40:20, Scott Hess wrote: > WRT your other question about whether -copyWithZone: is correct to implement, > technically it sure is, but practically it seldom is unless you're implementing > more at an infrastructure layer. For instance, you might copy over background > color and highlight mode, because all cells in the control will share it. But I > can't think of a case where you'd want to share match or description info > between cells. > > That's the general case. The specific case of NSTableView is that it sometimes > copies cells around internally, so for NSTableView cells using > -tableView:dataCellForTableColumn:row: style, I think you're supposed to > implement it. But you're using -tableView:willDisplayCell:forTableColumn:row:, > which I think just re-uses the same cell over and over. Yeah, it does seem to use the same cell over and over. A prior patch of this CL kept an array of cells that were reused. I could go back to that way of doing it (using dataCellForTableColumn). I could also do more preprocessing of the match data so less work is done in the willDisplayCell. Does either direction sound preferable? https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:19: NSInteger hovered_cell_; On 2015/05/04 19:40:20, Scott Hess wrote: > hovered_index_ or hovered_row_, since it's not the actual cell. Done. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return [array_ objectAtIndex:rowIndex]; On 2015/05/04 19:40:20, Scott Hess wrote: > This isn't a cell, though, it's a dictionary. Whoops, old comment. Removed now. Done. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:39: willDisplayCell:(id)aCell On 2015/05/04 19:40:20, Scott Hess wrote: > You should use ObjCCast<> or ObjCCastStrict<> to make this something more > specific than id before otherwise messaging it. One is "Give me one of these or > nil", the other is "Give me one of these or die", probably the latter is in > order here. Done. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:48: [aCell setMatch:acm->match_]; On 2015/05/04 19:40:20, Scott Hess wrote: > Since you manufacture the various internal info in -setMatch:, I don't think > setting all that information on every display is necessarily great. I'd > definitely drop a LOG(ERROR) somewhere and track how often more-expensive things > are being called when you do things like hover around. > > You might also want to find someone else to rope in who is more current on > NSTableView. It's possible my memories of which cases want to cache a bunch of > cells versus which cases want to just re-build the cell on the fly are wrong. It does get called during hover/highlight changes. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:110: - (void)setTheDelegate:(OmniboxPopupMatrixDelegate*)delegate { On 2015/05/04 19:40:20, Scott Hess wrote: > WRT our discussing in the CL, I worry that -setTheDelegate: is even worse than > -setCppDelegate:. Let's do the name change in another CL. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:44: [[AutocompleteMatchWrapper alloc] autorelease]; On 2015/05/04 19:40:21, Scott Hess wrote: > This object has been allocated but not initialized, you need an -init* of some > sort between +alloc and -autorelease. Done. https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:106: [[AutocompleteMatchWrapper alloc] autorelease]; On 2015/05/04 19:40:21, Scott Hess wrote: > -init in here, too. Done.
Hi Scott, This latest patch greatly reduced the number of cell redraws (based on your questions about how often the display code is called). It was redrawing all the cells repeatedly when moving the mouse over the drop down - even when moving side to side in the same cell. The new patch only redraws the prior cell and the new cell when changes are needed (minimum redraw) and moving the mouse within the cell is no redraw.
Once more, a drive-by. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:24: @interface OmniboxPopupCell : NSCell { We don't need any of NSButtonCell's behavior any more? https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:49: @property(nonatomic, readwrite, retain) NSAttributedString* attributedTitle; No need to specify readwrite - it's default. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:61: - (void)setTheDelegate:(OmniboxPopupMatrixDelegate*)delegate; I'm still objecting to the name. TheDelegate is not meaningful. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:66: // Select the row by turning it 'on'. Turns 'off' prior selection. Why the quotes? https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:38: - (void)tableView:(NSTableView*)aTableView I don't think we use the "aSmalltalkProperty" notation. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:95: - (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate { It's not really a MatrixDelegate any more, is it? https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:109: acm->match_ = match; Why not keep match and image in the wrapped match? (BTW: wrappedMatch is a more readable name than acm)
https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:24: @interface OmniboxPopupCell : NSCell { On 2015/05/07 02:39:58, groby wrote: > We don't need any of NSButtonCell's behavior any more? It doesn't seem so. I'm going by Jayson's advice and my local testing. The button cell had some handy features if we're only doing a simple image/text line. With the coming AiS changes much more of it will need to be done by us to get the layout we're doing. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:49: @property(nonatomic, readwrite, retain) NSAttributedString* attributedTitle; On 2015/05/07 02:39:58, groby wrote: > No need to specify readwrite - it's default. Done. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:61: - (void)setTheDelegate:(OmniboxPopupMatrixDelegate*)delegate; On 2015/05/07 02:39:59, groby wrote: > I'm still objecting to the name. TheDelegate is not meaningful. This is being changed to setObserver. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:66: // Select the row by turning it 'on'. Turns 'off' prior selection. On 2015/05/07 02:39:58, groby wrote: > Why the quotes? Because I thought on/off were odd labels for selection. I'm guessing the emphasis is odd to others so I'll remove the quotes. Done. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:38: - (void)tableView:(NSTableView*)aTableView On 2015/05/07 02:39:59, groby wrote: > I don't think we use the "aSmalltalkProperty" notation. Done. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:95: - (id)initWithDelegate:(OmniboxPopupMatrixDelegate*)delegate { On 2015/05/07 02:39:59, groby wrote: > It's not really a MatrixDelegate any more, is it? The Delegate names will change to observer. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:109: acm->match_ = match; On 2015/05/07 02:39:59, groby wrote: > Why not keep match and image in the wrapped match? (BTW: wrappedMatch is a more > readable name than acm) It feels like there are two opposing options to choose from. One is to go with a struct/class style to hold the data and another is to go with a dictionary style. I'd like to go one direction or the other, by either removing the dictionary local or breaking pieces out as separate key/value pairs in the dictionary. There's a higher level choice that can be made here. That is whether we should keep an array of NSCell objects or whether to keep an array of either structs or dictionaries. I'd like to chat about the options if we get a chance :) Done.
As mentioned earlier, I feel like we might be missing someone who knows answers to questions about NSTableView :-). https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/140001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:221: } On 2015/05/04 23:51:40, dschuyler wrote: > On 2015/05/04 19:40:20, Scott Hess wrote: > > WRT your other question about whether -copyWithZone: is correct to implement, > > technically it sure is, but practically it seldom is unless you're > implementing > > more at an infrastructure layer. For instance, you might copy over background > > color and highlight mode, because all cells in the control will share it. But > I > > can't think of a case where you'd want to share match or description info > > between cells. > > > > That's the general case. The specific case of NSTableView is that it > sometimes > > copies cells around internally, so for NSTableView cells using > > -tableView:dataCellForTableColumn:row: style, I think you're supposed to > > implement it. But you're using > -tableView:willDisplayCell:forTableColumn:row:, > > which I think just re-uses the same cell over and over. > > Yeah, it does seem to use the same cell over and over. > > A prior patch of this CL kept an array of cells that were reused. I could go > back to that way of doing it (using dataCellForTableColumn). I could also do > more preprocessing of the match data so less work is done in the > willDisplayCell. Does either direction sound preferable? This is something I'm not entirely certain of. It seems to me that recalculating the NSAttributedString on every display may be somewhat poor - not a huge horrible thing, but it does seem like excess work. It's harder to avoid recalculating the info involved with actually drawing the NSAttributedString. Of course if the entire thing is drawn into some interesting buffer-backed layer thing, all of this hardly matters. I would guess if you dropped some logging in, you'd find a burst of set-the-cell-up for every cell on popup, then pairs for highlight/unhighlight as you move around. And hover/unhover? If it's down to just that constant amount of setup per user event, then using the same cell repeatedly is defensible, but if it's "I'm going to redraw the entire thing" on every user event, then I'm more inclined to think a bit of caching in an array of cells is in order. https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/180001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:109: acm->match_ = match; On 2015/05/07 20:53:10, dschuyler wrote: > On 2015/05/07 02:39:59, groby wrote: > > Why not keep match and image in the wrapped match? (BTW: wrappedMatch is a > more > > readable name than acm) > > It feels like there are two opposing options to choose from. One is to go with > a struct/class style to hold the data and another is to go with a dictionary > style. I'd like to go one direction or the other, by either removing the > dictionary local or breaking pieces out as separate key/value pairs in the > dictionary. Keep in mind that we're an Objective-C++ project, and C++ is really common. Boxing C structures in Objective-C objects is a very FoundationKit thing to do, but when you can just as easily use an STL container without all the boxing, I'd say go with that. The results sometimes look funky, but IMHO things like -valueWithRect: are already pretty funky. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); This is an unexpected approach. Why do you need the above three lines and the later lines which call reset() on self's instance variables? The copy should have nil in each of these slots. If it's super C++-aware, it should have an additional reference in each of these slots, which gets replaced with the copy below. I don't expect it's super C++-aware, though. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:373: / 2.0); As long as you're on two lines, just pull everything after the += on to this line to make the parens clearer. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:375: [as drawInRect:FlipIfRTL(renderRect, cellFrame)]; I think the style in here is to drop the {} when it goes to single-line body. [I don't like that style myself, but still have to follow the local style.] https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:22: [[test_window() contentView] addSubview:control_]; Feel free to embiggen these tests. At some point the goal in here was just to make sure it was passing very basic functionality, like setters and getters don't freak out, but I think the cell got more complicated without any attention to the tests. [No need for this CL, you're not making it worse, but as long as you're in here for a few days/weeks, might as well make it better.] https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:66: // Select the row by turning it on. Turns off prior selection. IMHO, using on and off are themselves weird, they're just implementation details. "Move the selection to |rowIndex|." seems reasonable. Though I'm always willing to fly without comments if the comment adds nothing above the literal method signature. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: } This method feels weird, like it's taking this value and putting it somewhere for your to use later, but you never use it. Does it really need a distinct object, like can you return self or nil? Or can you not implement it at all? [I see documentation which seems to indicate both that you must implement the above two methods, and that you only have to implement -numberOfRowsInTableView:] https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:67: } {} aren't needed here. Actually, I'd rewrite this line as return, and the next line as return NSZeroRect. Or vice versa. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:31: matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]); Matrix is seeming misleading! https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:37: [matrix_ addTableColumn:[column retain]]; Seems like the receiver is going to -retain, so this is one too many. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:39: NSInteger testHeight = 25; CGFloat, since they're floats in use below. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:42: NSInteger popupHeight = 0; CGFloat here, too. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:101: NSInteger popupHeight = 0; CGFloat. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:103: cellRect.size.width = NSWidth([field_ bounds]); Actually, just set it to [field_ bounds], so that origin.x is also initialized. Almost always bounds origin is at {0,0}, so it's equivalent, but this way you can combine these two lines. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:109: acm->match_ = match; Starting to wonder if you shouldn't rather implement [AutocompleteMatchWrapper wrapperWithMatch:match], since every use does this. Though my other comment suggested that you might just consider STL structures rather than NSArray of NSDictionary of boxed values. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:118: popupHeight += height; I'd set cellRect.size.height directly, then use NSHeight(cellRect) here (or cellRect.size.height if you think it makes more sense). My reasoning is that the various aliases may-or-may-not maintain their equivalence as people make changes to the code, so only have one value. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:123: popupHeight += [matrix_ intercellSpacing].height * (rows - 1); WDYT of having the entire loop in this if()? That said, some people would argue that the DCHECK_GT() above means you shouldn't bother with this if().
Dave and I discussed the magic of -copyWithZone: offline, sorry for forgetting to update the CL. Short version: Legacy shortcuts will haunt us forever. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/07 22:35:42, Scott Hess wrote: > This is an unexpected approach. Why do you need the above three lines and the > later lines which call reset() on self's instance variables? > > The copy should have nil in each of these slots. If it's super C++-aware, it > should have an additional reference in each of these slots, which gets replaced > with the copy below. I don't expect it's super C++-aware, though. This is here due to NSCopyObject. NSCell uses that in its copyWithZone (or so lore has it, I haven't disassembled the SDK recently), and so [super copyWithZone:] makes a bitwise copy of this object. Which means not only that the slots aren't nil, but that the retain counts are messed up. And so, we need to * Transfer scoped objects to temp vars (so we don't lose them) and nil out these slots. That's what release() is for * Create an actual copy of those objects and retain it on the copied cell * Store the old objects in the slots in the current object. Mike Ash has a nice article on this[1]. He also has a slightly more elegant way, but that assumes that scoped_nsobject is an NSObject*. Which it is, but we probably don't want to rely on this or leak the implementation detail here. [1] https://www.mikeash.com/pyblog/friday-qa-2010-08-27-defensive-programming-in-... https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:212: copy->separator_.reset([separator copy]); You technically don't need to copy the NSAttributedString - none of them are mutable, and so you're free to simply retain the original one. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:123: popupHeight += [matrix_ intercellSpacing].height * (rows - 1); On 2015/05/07 22:35:42, Scott Hess wrote: > WDYT of having the entire loop in this if()? > > That said, some people would argue that the DCHECK_GT() above means you > shouldn't bother with this if(). +1 on "don't bother". Either we assert rows is *always* >0, or we check rows. In fact, I'd even kill the DCHECK - the code is essentially if (rows == 0) { ... return; } DCHECK_GT(rows, 0) It's an odd assertion to make. (It's trivially true, and a decent compiler will probably eliminate it completely anyways) What I _would_ like to see DCHECK'd is (start_match >= result.size())
https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/08 03:24:08, groby wrote: > On 2015/05/07 22:35:42, Scott Hess wrote: > > This is an unexpected approach. Why do you need the above three lines and the > > later lines which call reset() on self's instance variables? > > > > The copy should have nil in each of these slots. If it's super C++-aware, it > > should have an additional reference in each of these slots, which gets > replaced > > with the copy below. I don't expect it's super C++-aware, though. > > This is here due to NSCopyObject. NSCell uses that in its copyWithZone (or so > lore has it, I haven't disassembled the SDK recently), and so [super > copyWithZone:] makes a bitwise copy of this object. Which means not only that > the slots aren't nil, but that the retain counts are messed up. > > And so, we need to > * Transfer scoped objects to temp vars (so we don't lose them) and nil out > these slots. That's what release() is for > * Create an actual copy of those objects and retain it on the copied cell > * Store the old objects in the slots in the current object. > > Mike Ash has a nice article on this[1]. He also has a slightly more elegant way, > but that assumes that scoped_nsobject is an NSObject*. Which it is, but we > probably don't want to rely on this or leak the implementation detail here. > > [1] > https://www.mikeash.com/pyblog/friday-qa-2010-08-27-defensive-programming-in-... W. T. F. In that case, might I suggest: scoped_nsobject<NSAttributedString> separator(separator_.release()); //... copy->separator_.reset([separator copy]); //... separator_.swap(separator); As the base reference gives me the willies. Also, maybe a comment on the order of "This is crazy because NSCell's -copyFromZone: is crazy", so that some later Good Samaritan doesn't clean it up for you. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:212: copy->separator_.reset([separator copy]); On 2015/05/08 03:24:08, groby wrote: > You technically don't need to copy the NSAttributedString - none of them are > mutable, and so you're free to simply retain the original one. If they aren't mutable, then -copy should be implemented as -retain.
My apologies... At least I didn't discuss the variant that involves separator(separator_.autorelease()) :) https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/08 04:11:48, Scott Hess wrote: > On 2015/05/08 03:24:08, groby wrote: > > On 2015/05/07 22:35:42, Scott Hess wrote: > > > This is an unexpected approach. Why do you need the above three lines and > the > > > later lines which call reset() on self's instance variables? > > > > > > The copy should have nil in each of these slots. If it's super C++-aware, > it > > > should have an additional reference in each of these slots, which gets > > replaced > > > with the copy below. I don't expect it's super C++-aware, though. > > > > This is here due to NSCopyObject. NSCell uses that in its copyWithZone (or so > > lore has it, I haven't disassembled the SDK recently), and so [super > > copyWithZone:] makes a bitwise copy of this object. Which means not only that > > the slots aren't nil, but that the retain counts are messed up. > > > > And so, we need to > > * Transfer scoped objects to temp vars (so we don't lose them) and nil out > > these slots. That's what release() is for > > * Create an actual copy of those objects and retain it on the copied cell > > * Store the old objects in the slots in the current object. > > > > Mike Ash has a nice article on this[1]. He also has a slightly more elegant > way, > > but that assumes that scoped_nsobject is an NSObject*. Which it is, but we > > probably don't want to rely on this or leak the implementation detail here. > > > > [1] > > > https://www.mikeash.com/pyblog/friday-qa-2010-08-27-defensive-programming-in-... > > W. T. F. > > In that case, might I suggest: > scoped_nsobject<NSAttributedString> separator(separator_.release()); > //... > copy->separator_.reset([separator copy]); > //... > separator_.swap(separator); > As the base reference gives me the willies. Also, maybe a comment on the order > of "This is crazy because NSCell's -copyFromZone: is crazy", so that some later > Good Samaritan doesn't clean it up for you. I hate to be the contrarian, but... Assume a separator_ with refcount 1. The release nils separator_, *without* affecting refcount. (release doesn't release, because... scoped_ptr::release doesn't deref either. No, I don't think that's a good enough reason, but hey.) But scoped_nsobject's constructor _does_ retain, and so we now have a refcount of 2. So at that point, swap() won't do the trick since separator_ has an increased refcount. The last line would need to be separator_.reset(separator.get()); reset() doesn't retain, so both separator_ and separator now hold the same object, with refcount 2. When separator goes out of scope, the object still has a refcount of 1. Oh yes, it's _that_ awesome. (Or I should be home instead of thinking about refcounts. One of the two) Alternative: scoped_nsobject<NSAttributedString> separator; separator.reset(separator_.release()); copy->separator_.reset([separator copy]); separator_.swap(separator); Alternative 2: scoped_nsobject<NSAttributedString> separator(separator_); separator_.reset(); copy->separator_.reset([separator copy]); separator_ = separator(); The last one is the cleanest one to me: Take a local reference, release the ivar reference and nil it, make a copy of the local object, ivar references local object, scoped_nsobject dtor releases local reference Any of these versions probably should come with a "call me crazy, maybe" comment so the next person won't go through this entire dance again. To cheer all of you up: 10.10 is moving along with deprecating NSCell. Another 10 years or so, and we'll never have to think about this :)
https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/08 05:08:29, groby wrote: > Alternative: > scoped_nsobject<NSAttributedString> separator; > separator.reset(separator_.release()); > copy->separator_.reset([separator copy]); > separator_.swap(separator); > > Alternative 2: > scoped_nsobject<NSAttributedString> separator(separator_); > separator_.reset(); > copy->separator_.reset([separator copy]); > separator_ = separator(); > > The last one is the cleanest one to me: Take a local reference, release the ivar > reference and nil it, make a copy of the local object, ivar references local > object, scoped_nsobject dtor releases local reference Alternative 3: scoped_nsobject<NSAttributedString> separator; separator.swap(separator_); copy->separator_.reset([separator copy]); separator_.swap(separator); I can never quite wrap my head around whether it would make sense to have Pass(), so you could wrote: scoped_nsobject<NSAttributedString> separator(separator_.Pass()); copy->separator_.reset([separator copy]); separator_.swap(separator); Probably too dangerous to exist. > To cheer all of you up: 10.10 is moving along with deprecating NSCell. Another > 10 years or so, and we'll never have to think about this :) Eh, I remember figuring out NSControl/NSCell and thinking "Yeah, that makes sense given implementation issues" and moving on. But then again I thought autorelease also made perfect sense when you thought about the implementation. I have recently come to suspect that many people manage to become professional programmers without spending time thinking out how they'd implement the libraries they use. Fortunately in the future Apple will be free to use memcpy()-style replication of objects in view-based widget hierarchies, so it's all good. [I kid, they'll be using Swift, so memcpy() won't be available.]
Oh, memcpy is callable from Swift. You shouldn't, but neither should you do the nonsense that NSCopyObject commits. So I'm looking forward to new interesting things for a long time ;) https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/08 06:00:13, Scott Hess wrote: > On 2015/05/08 05:08:29, groby wrote: > > Alternative: > > scoped_nsobject<NSAttributedString> separator; > > separator.reset(separator_.release()); > > copy->separator_.reset([separator copy]); > > separator_.swap(separator); > > > > Alternative 2: > > scoped_nsobject<NSAttributedString> separator(separator_); > > separator_.reset(); > > copy->separator_.reset([separator copy]); > > separator_ = separator(); > > > > The last one is the cleanest one to me: Take a local reference, release the > ivar > > reference and nil it, make a copy of the local object, ivar references local > > object, scoped_nsobject dtor releases local reference > > Alternative 3: > scoped_nsobject<NSAttributedString> separator; > separator.swap(separator_); > copy->separator_.reset([separator copy]); > separator_.swap(separator); > I can never quite wrap my head around whether it would make sense to have > Pass(), so you could wrote: > scoped_nsobject<NSAttributedString> separator(separator_.Pass()); > copy->separator_.reset([separator copy]); > separator_.swap(separator); > Probably too dangerous to exist. > > > To cheer all of you up: 10.10 is moving along with deprecating NSCell. Another > > 10 years or so, and we'll never have to think about this :) > > Eh, I remember figuring out NSControl/NSCell and thinking "Yeah, that makes > sense given implementation issues" and moving on. But then again I thought > autorelease also made perfect sense when you thought about the implementation. > I have recently come to suspect that many people manage to become professional > programmers without spending time thinking out how they'd implement the > libraries they use. Fortunately in the future Apple will be free to use > memcpy()-style replication of objects in view-based widget hierarchies, so it's > all good. > > [I kid, they'll be using Swift, so memcpy() won't be available.] I like the symmetry of #3. I'm reasonably certain it deals with the refcount properly, but it's late. I'd suggest debug printing them to make sure.
https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* prefix = prefix_.release(); On 2015/05/08 06:20:43, groby wrote: > I like the symmetry of #3. I'm reasonably certain it deals with the refcount > properly, but it's late. I'd suggest debug printing them to make sure. Another option which just occurred to me would be to give up entirely and strip your NSCell down to POD and weak pointers. For instance, a pointer (not a reference) to the data source plus the cell's index. This is an atrocity, but my assumption is that if NSCopyObject() isn't doing the right thing WRT Objective-C ref-counting, then it is also unlikely to be doing the right thing WRT C++ copying. So if someone later changes AutocompleteMatch to internally use something ref-counted, that's also potentially messed up. This is going to bother me for weeks.
On 2015/05/08 18:25:50, Scott Hess wrote: > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* > prefix = prefix_.release(); > On 2015/05/08 06:20:43, groby wrote: > > I like the symmetry of #3. I'm reasonably certain it deals with the refcount > > properly, but it's late. I'd suggest debug printing them to make sure. > > Another option which just occurred to me would be to give up entirely and strip > your NSCell down to POD and weak pointers. For instance, a pointer (not a > reference) to the data source plus the cell's index. This is an atrocity, but > my assumption is that if NSCopyObject() isn't doing the right thing WRT > Objective-C ref-counting, then it is also unlikely to be doing the right thing > WRT C++ copying. So if someone later changes AutocompleteMatch to internally > use something ref-counted, that's also potentially messed up. > > This is going to bother me for weeks. Yes, -copyWithZone/NSCell is dangerous. But so are naked pointers. I'd really rather not give up ref counting, praying the data source stays alive. We already do the same thing for the HyperlinkButtonCell, so I'd suggest leaving this as is. With a big fat warning both here and in the header that THAR BE DRAGONS, and you better know what you do. ObWhine: Can we please move to 10.7, so we can abandon cell based NSTableView objects?
On 2015/05/08 18:46:29, groby wrote: > On 2015/05/08 18:25:50, Scott Hess wrote: > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): > > > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:209: NSAttributedString* > > prefix = prefix_.release(); > > On 2015/05/08 06:20:43, groby wrote: > > > I like the symmetry of #3. I'm reasonably certain it deals with the refcount > > > properly, but it's late. I'd suggest debug printing them to make sure. > > > > Another option which just occurred to me would be to give up entirely and > strip > > your NSCell down to POD and weak pointers. For instance, a pointer (not a > > reference) to the data source plus the cell's index. This is an atrocity, but > > my assumption is that if NSCopyObject() isn't doing the right thing WRT > > Objective-C ref-counting, then it is also unlikely to be doing the right thing > > WRT C++ copying. So if someone later changes AutocompleteMatch to internally > > use something ref-counted, that's also potentially messed up. > > > > This is going to bother me for weeks. > > Yes, -copyWithZone/NSCell is dangerous. But so are naked pointers. I'd really > rather not give up ref counting, praying the data source stays alive. > > We already do the same thing for the HyperlinkButtonCell, so I'd suggest leaving > this as is. With a big fat warning both here and in the header that THAR BE > DRAGONS, and you better know what you do. > > ObWhine: Can we please move to 10.7, so we can abandon cell based NSTableView > objects? Oh, and to address Scott's concern around |match_| not being properly copied: Why do we store that at all? After we create a bunch of strings in -setMatch:, we seem to not touch it?
I had a couple false-starts on different directions. How does this one look? It now pre-digests the match information into a cell data class. The array of suggestions is made up of those instances - the NSCell code uses the re-used NSCell scheme in NSTableView. The setup for the NSCell is now just setting an entry for the cell data instance (the code no longer re-processes the match description each time the NSCell is setup. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:373: / 2.0); On 2015/05/07 22:35:42, Scott Hess wrote: > As long as you're on two lines, just pull everything after the += on to this > line to make the parens clearer. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:375: [as drawInRect:FlipIfRTL(renderRect, cellFrame)]; On 2015/05/07 22:35:42, Scott Hess wrote: > I think the style in here is to drop the {} when it goes to single-line body. > > [I don't like that style myself, but still have to follow the local style.] Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:22: [[test_window() contentView] addSubview:control_]; On 2015/05/07 22:35:42, Scott Hess wrote: > Feel free to embiggen these tests. At some point the goal in here was just to > make sure it was passing very basic functionality, like setters and getters > don't freak out, but I think the cell got more complicated without any attention > to the tests. > > [No need for this CL, you're not making it worse, but as long as you're in here > for a few days/weeks, might as well make it better.] Acknowledged. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h:66: // Select the row by turning it on. Turns off prior selection. On 2015/05/07 22:35:42, Scott Hess wrote: > IMHO, using on and off are themselves weird, they're just implementation > details. "Move the selection to |rowIndex|." seems reasonable. Though I'm > always willing to fly without comments if the comment adds nothing above the > literal method signature. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: } On 2015/05/07 22:35:42, Scott Hess wrote: > This method feels weird, like it's taking this value and putting it somewhere > for your to use later, but you never use it. Does it really need a distinct > object, like can you return self or nil? Or can you not implement it at all? > [I see documentation which seems to indicate both that you must implement the > above two methods, and that you only have to implement > -numberOfRowsInTableView:] Returning nil seems fine, if that's preferable. From what I've read, for this style of table view, it should be implemented. I also agree that it's a bit strange, but I think their intention is that the data source and the delegate might be separate objects. If that were the case it may be useful to pass the data through an intermediary. The docs also suggest making the delegate and the data source the same object. In which case, passing the data through an intermediary is odd. Also, rereading the docs pointed out that we need a setObjectValue function as well. I've defined one as a formality. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:67: } On 2015/05/07 22:35:42, Scott Hess wrote: > {} aren't needed here. > > Actually, I'd rewrite this line as return, and the next line as return > NSZeroRect. Or vice versa. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:31: matrix_.reset([[OmniboxPopupMatrix alloc] initWithDelegate:this]); On 2015/05/07 22:35:42, Scott Hess wrote: > Matrix is seeming misleading! I'd like to separate the name change to another CL. Either before or after this CL. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:37: [matrix_ addTableColumn:[column retain]]; On 2015/05/07 22:35:42, Scott Hess wrote: > Seems like the receiver is going to -retain, so this is one too many. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:39: NSInteger testHeight = 25; On 2015/05/07 22:35:42, Scott Hess wrote: > CGFloat, since they're floats in use below. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:42: NSInteger popupHeight = 0; On 2015/05/07 22:35:42, Scott Hess wrote: > CGFloat here, too. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:101: NSInteger popupHeight = 0; On 2015/05/07 22:35:42, Scott Hess wrote: > CGFloat. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:109: acm->match_ = match; On 2015/05/07 22:35:42, Scott Hess wrote: > Starting to wonder if you shouldn't rather implement [AutocompleteMatchWrapper > wrapperWithMatch:match], since every use does this. Though my other comment > suggested that you might just consider STL structures rather than NSArray of > NSDictionary of boxed values. Yeah, that makes sense. The wrapper class is gone now. There's a new class that tracks the digested info from the match (without storing the match itself). I put the init with match on that class. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:118: popupHeight += height; On 2015/05/07 22:35:42, Scott Hess wrote: > I'd set cellRect.size.height directly, then use NSHeight(cellRect) here (or > cellRect.size.height if you think it makes more sense). My reasoning is that > the various aliases may-or-may-not maintain their equivalence as people make > changes to the code, so only have one value. I used cellRect.size.height because for readability I think it's clearer that it's using the value calculated above. It's easier to see that cellRect.size.height is the same. Done. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:123: popupHeight += [matrix_ intercellSpacing].height * (rows - 1); On 2015/05/07 22:35:42, Scott Hess wrote: > WDYT of having the entire loop in this if()? > > That said, some people would argue that the DCHECK_GT() above means you > shouldn't bother with this if(). I went with the DCHECK_GT option :)
https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:37: bool isContentsRTL_; Should this be C++ bool or ObjC BOOL? For ObjC classes I've made it BOOL. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:52: - (void)setRect:(NSRect)rect; Should be able to get rid of setRect: and rect declarations and definitions in the .mm, and replace with a property: @property (assign, nonatomic) NSRect rect; and in the .mm @synthesize rect = rect_; https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:289: NSImage* image = image_; Why do you have to create a local variable instead of use image_ directly? https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: [popupCell setCellData:cellData]; Is it OK to just say [popupCell setCellData:[array_ objectAtIndex:rowIndex]]; It doesn't look like cellData is used anywhere except this one spot. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:163: } Seems like above you'd want to say NSIndexSet* indexSet = nil; and then here say } else { indexSet = [NSIndexSet indexSet]; } to avoid creating and throwing away an index set if the condition is true?
https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:37: bool isContentsRTL_; On 2015/05/14 18:02:38, shrike wrote: > Should this be C++ bool or ObjC BOOL? For ObjC classes I've made it BOOL. Done. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:52: - (void)setRect:(NSRect)rect; On 2015/05/14 18:02:39, shrike wrote: > Should be able to get rid of setRect: and rect declarations and definitions in > the .mm, and replace with a property: > > @property (assign, nonatomic) NSRect rect; > > and in the .mm > > @synthesize rect = rect_; Thanks, I had wondered which way would be preferred. Done. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:289: NSImage* image = image_; On 2015/05/14 18:02:39, shrike wrote: > Why do you have to create a local variable instead of use image_ directly? It was done that was previously. I'm not sure why. Done. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: [popupCell setCellData:cellData]; On 2015/05/14 18:02:39, shrike wrote: > Is it OK to just say > > [popupCell setCellData:[array_ objectAtIndex:rowIndex]]; > > It doesn't look like cellData is used anywhere except this one spot. From an obj-C point of view, it seems fine to do so. From a coding style point of view, I'm unsure of the answer. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:163: } On 2015/05/14 18:02:39, shrike wrote: > Seems like above you'd want to say > > NSIndexSet* indexSet = nil; > > and then here say > > } else { > indexSet = [NSIndexSet indexSet]; > } > > to avoid creating and throwing away an index set if the condition is true? Done.
Thanks for bearing with us. https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: } On 2015/05/13 01:41:11, dschuyler wrote: > On 2015/05/07 22:35:42, Scott Hess wrote: > > This method feels weird, like it's taking this value and putting it somewhere > > for your to use later, but you never use it. Does it really need a distinct > > object, like can you return self or nil? Or can you not implement it at all? > > [I see documentation which seems to indicate both that you must implement the > > above two methods, and that you only have to implement > > -numberOfRowsInTableView:] > > Returning nil seems fine, if that's preferable. > > From what I've read, for this style of table view, it should be implemented. > > I also agree that it's a bit strange, but I think their intention is that the > data source and the delegate might be separate objects. If that were the case > it may be useful to pass the data through an intermediary. > > The docs also suggest making the delegate and the data source the same object. > In which case, passing the data through an intermediary is odd. > > Also, rereading the docs pointed out that we need a setObjectValue function as > well. I've defined one as a formality. [I haven't yet gotten to the current code.] Mostly I mean that this object goes off into the ether and never returns. Seems to me like the framework should ask for the object, then store it somewhere, and elsewhere your code can ask for that stored object, then act on it. The fact that it's not working that way makes me wonder if something is wrong. [Again, I haven't yet gotten to the current code. If I forget to circle back on this comment, ignore it if a later comment makes more sense.] https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:37: bool isContentsRTL_; On 2015/05/14 18:02:38, shrike wrote: > Should this be C++ bool or ObjC BOOL? For ObjC classes I've made it BOOL. I think that in general Objective-C should use BOOL/YES/NO, C++ bool/true/false, except at the intersection where you make things up. I think that you can also just let things leak across without having to write things like "cpp_bool = objc_BOOL ? true : false;". Basically aim for consistency, I guess, like if some code would look the same for the OSX code as the Views code, then better to be the same rather than egregiously convert things. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:289: NSImage* image = image_; On 2015/05/14 22:28:20, dschuyler wrote: > On 2015/05/14 18:02:39, shrike wrote: > > Why do you have to create a local variable instead of use image_ directly? > > It was done that was previously. I'm not sure why. > > Done. I suspect [self image] was using the cell's image storage. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:52: [popupCell setCellData:cellData]; On 2015/05/14 22:28:20, dschuyler wrote: > On 2015/05/14 18:02:39, shrike wrote: > > Is it OK to just say > > > > [popupCell setCellData:[array_ objectAtIndex:rowIndex]]; > > > > It doesn't look like cellData is used anywhere except this one spot. > > From an obj-C point of view, it seems fine to do so. > From a coding style point of view, I'm unsure of the answer. I think it's OK, or to have cellData not be a scoped_nsobject<>(). The difference from my earlier point about using a scoper was that you should prefer a scoper to using an -autorelease, but in this case the -autorelease is already implied, so taking advantage of it to simplify things is fine. Actually, since -retain also has a cost, taking advantage of the known-good reference is probably preferred to nailing it down with another reference. Light preference, I wouldn't contort the code for it, but in this case you wouldn't contort the code. Doing it all on one line as Jayson suggests is good, because it minimizes the span of code where you have to rely on convention for correctness. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:163: } On 2015/05/14 22:28:20, dschuyler wrote: > On 2015/05/14 18:02:39, shrike wrote: > > Seems like above you'd want to say > > > > NSIndexSet* indexSet = nil; > > > > and then here say > > > > } else { > > indexSet = [NSIndexSet indexSet]; > > } > > > > to avoid creating and throwing away an index set if the condition is true? > > Done. Double-check that -selectRowIndexes: allows for nil there. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:76: inView:(NSView*)controlView; If this is only being exposed so that the cell implementation can call it, then you can either put this method before the calling method, or add it to a private category, rather than exposing it here. A private category would be in the .mm file, and might look like: @interface OmniboxPopupCell (private) // Methods in the category. @end [I was going to ask for a comment, but then realized that it's not really something anyone else should be calling.] https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; Ack! Chromium style conflicts with my years of Objective-C experience! Hmm, I think go with it, this is too long otherwise, unless you add a helper. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:170: [CreateAttributedString(raw_separator, DimTextColor()) retain]); Note that scoped_nsobject<> implements operator= to include the retain. So this could be: separator_ = [...]; I am not suggesting that you make that change, just pointing it out. I'm kind of feeling that a retain() function would make sense, really, to make it clear that code is saying "Take a reference to this object and keep it." https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:200: answerString += space + textField->text(); I find my brain really questioning this. I'd guess it implies that text() is returning an std::string or a base::string16? If it was: answerString.append(space).append(text()); I wouldn't have to think that through, and it would work even if someone changes text() return, and it also wouldn't create the intermediate object. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:237: // dschuyler about why it's written with swaps and local data. Consult with Rachel, first, but ... in this case, we control the horizontal and the vertical, so we don't have to live with NSCell's mistakes. Since you're creating a new object below, not calling [super copyWithZone:zone], that new object has no references to self's instance variables the screw up, so you can either call accessors to set things, or copy->instance_var_ directly. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:378: // dschuyler about why it's written with swaps and local data. Now _this_ code has to keep the crazy. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:379: base::scoped_nsobject<OmniboxPopupCellData> cellData(nil); Though I think the (nil) can be disposed of. It's default to nil. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:380: cellData_.swap(cellData); And I would say cellData.swap(cellData_), to make it clear where the reference ends up. It's exactly the same code in the end, but we (at least I) are tuned to expect things to end up in the LHS. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: array_.reset([[NSMutableArray alloc] init]); Use NSArray, here. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:100: [column setDataCell:[[[OmniboxPopupCell alloc] init] autorelease]]; This is a case where putting the cell in an scoped_nsobject<> saves you a tiny fraction of a CPU. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:100: NSMutableArray* array = [NSMutableArray array]; I'd also do scoped_nsobject<> of [[NSMutableArray alloc] init] here. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:114: [cellData setImage:image]; Should these be individual setters, or should the designated initializer be something like -initWithMatch:rect:image:? Also, should the image be calculated here, or should the cell data calculate it from the match? Hmm, and should the cell data even have a rect? Isn't the rect defined by the cell which the cellData is put into? What would happen if the rect set here conflicted with the rect the cell is being drawn into? https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:165: } Nevermind my earlier (or later?) comment, this is right. I misunderstood the suggestion, and am too tired to find my other comment.
https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:37: bool isContentsRTL_; On 2015/05/15 00:09:38, Scott Hess wrote: > On 2015/05/14 18:02:38, shrike wrote: > > Should this be C++ bool or ObjC BOOL? For ObjC classes I've made it BOOL. > > I think that in general Objective-C should use BOOL/YES/NO, C++ bool/true/false, > except at the intersection where you make things up. I think that you can also > just let things leak across without having to write things like "cpp_bool = > objc_BOOL ? true : false;". Basically aim for consistency, I guess, like if > some code would look the same for the OSX code as the Views code, then better to > be the same rather than egregiously convert things. The "accepted way" to go from BOOL to bool is the '!!' trick. I.e BOOL cocoaVar = YES; bool cppVar = !!cocoaVar; https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:76: inView:(NSView*)controlView; On 2015/05/15 00:09:38, Scott Hess wrote: > If this is only being exposed so that the cell implementation can call it, then > you can either put this method before the calling method, or add it to a private > category, rather than exposing it here. > > A private category would be in the .mm file, and might look like: > > @interface OmniboxPopupCell (private) > // Methods in the category. > @end > > [I was going to ask for a comment, but then realized that it's not really > something anyone else should be calling.] If it's a purely private category in a .mm, I'd suggest an anonymous one - i.e @interface OmniboxPopupCell () Two adavantages - one, implementation of the methods is mandatory, and two, nobody can later go and re-declare the category elsewhere and still use it. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 00:09:38, Scott Hess wrote: > Ack! Chromium style conflicts with my years of Objective-C experience! > > Hmm, I think go with it, this is too long otherwise, unless you add a helper. This is really rubbing all ObjC senses the wrong way - I'd second the idea of a helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer will double take on this :) https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:237: // dschuyler about why it's written with swaps and local data. On 2015/05/15 00:09:38, Scott Hess wrote: > Consult with Rachel, first, but ... in this case, we control the horizontal and > the vertical, so we don't have to live with NSCell's mistakes. Since you're > creating a new object below, not calling [super copyWithZone:zone], that new > object has no references to self's instance variables the screw up, so you can > either call accessors to set things, or copy->instance_var_ directly. Rachel is fully supportive of that argument :) That is, if we need copyWithZone at all. I don't think we do. As far as I can tell, CellData is an immutable object _as far as the cell is concerned_. So kill all this, and in the cell's -copyWithZone just do a copy->cellData_ = [cellData_ retain]; (If I miss something and you _do_ need to copy this, you should mark the CellData class as conforming to NSCopying) https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:114: [cellData setImage:image]; On 2015/05/15 00:09:38, Scott Hess wrote: > Should these be individual setters, or should the designated initializer be > something like -initWithMatch:rect:image:? > > Also, should the image be calculated here, or should the cell data calculate it > from the match? > > Hmm, and should the cell data even have a rect? Isn't the rect defined by the > cell which the cellData is put into? What would happen if the rect set here > conflicted with the rect the cell is being drawn into? I'd prefer -initWithMatch:image - because that way, we can remove the setter and make clear that yes, cellData is immutable. (See previous comment on copyWithZone) And yes, the rect should be on the cell.
https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:237: // dschuyler about why it's written with swaps and local data. On 2015/05/15 16:53:56, groby wrote: > So kill all this, and in the cell's -copyWithZone just do a copy->cellData_ = > [cellData_ retain]; operator= already implies retain, so either copy->cellData_ = cellData_, or copy->cellData_.reset([celldata_ retain]). The cell's -copyWithZone: actually already does the operator= version, so AFAICT this method is never called. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth), Oooh, maybe give this code a once-over for inappropriate casting. This looks to me like *contentsMaxWidth should really be a CGFloat, since -drawMatchPart:* is just casting it back. Apologies that this got to here, I seem to remember the original review of this code was pretty involved. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:114: [cellData setImage:image]; On 2015/05/15 16:53:56, groby wrote: > On 2015/05/15 00:09:38, Scott Hess wrote: > > Should these be individual setters, or should the designated initializer be > > something like -initWithMatch:rect:image:? > > > > Also, should the image be calculated here, or should the cell data calculate > it > > from the match? > > > > Hmm, and should the cell data even have a rect? Isn't the rect defined by the > > cell which the cellData is put into? What would happen if the rect set here > > conflicted with the rect the cell is being drawn into? > > I'd prefer -initWithMatch:image - because that way, we can remove the setter and > make clear that yes, cellData is immutable. (See previous comment on > copyWithZone) > > And yes, the rect should be on the cell. I don't think it can get to zero setters, because -setMaxMatchContentsWidth: needs to receive the accumulated-across-the-loop data, and I'm not entirely sure having separate initializers for with/without-contentsOffset: (plus associated if/else up here) is worth it. AFAICT, since maxMatchContentsWidth_ is only used at display time, it could be a single attribute of the display cell rather than a duplicated attribute of the displayed data. But that would just require adding parameters to pass it around in the display code, so practically I'm not sure it's worthwhile. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:121: contents_offset = [OmniboxPopupCell computeContentsOffset:match]; Does this helper still belong in the cell class, or in the data class? Not really arguing for either way, but having the width calculation just above move to the data object is suggestive. Making it an instance variable might also make sense, like: [cellData computeContentsOffset];
Thanks again! In an email I asked about how to test the TAIL and prefix bits of code. That is a wip at the moment. I'm not able to test changes to those areas as well as I'd like, so I'd like to minimize changes to them for this CL. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:37: bool isContentsRTL_; On 2015/05/15 16:53:56, groby wrote: > On 2015/05/15 00:09:38, Scott Hess wrote: > > On 2015/05/14 18:02:38, shrike wrote: > > > Should this be C++ bool or ObjC BOOL? For ObjC classes I've made it BOOL. > > > > I think that in general Objective-C should use BOOL/YES/NO, C++ > bool/true/false, > > except at the intersection where you make things up. I think that you can > also > > just let things leak across without having to write things like "cpp_bool = > > objc_BOOL ? true : false;". Basically aim for consistency, I guess, like if > > some code would look the same for the OSX code as the Views code, then better > to > > be the same rather than egregiously convert things. > > The "accepted way" to go from BOOL to bool is the '!!' trick. I.e > BOOL cocoaVar = YES; > bool cppVar = !!cocoaVar; > I tried this: changed it to BOOL as well as changing the isRTL elsewhere that it gets compared to. Then used !! to convert to BOOL. Then I reasoned: this is only used in a cpp domain (with values to/from cpp) and the code is simpler to keep in cpp. So, I changed it back to bool. I'm trying to read into the spirit of the suggestions being made, to keep the code easy to read and follow. For this particular case I *think* that bool may be the right way to go. https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/280001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:163: } On 2015/05/15 00:09:38, Scott Hess wrote: > On 2015/05/14 22:28:20, dschuyler wrote: > > On 2015/05/14 18:02:39, shrike wrote: > > > Seems like above you'd want to say > > > > > > NSIndexSet* indexSet = nil; > > > > > > and then here say > > > > > > } else { > > > indexSet = [NSIndexSet indexSet]; > > > } > > > > > > to avoid creating and throwing away an index set if the condition is true? > > > > Done. > > Double-check that -selectRowIndexes: allows for nil there. Passing nil to selectRowIndexes doesn't appear to be harmful (based on testing). The docs are not clear on it that I've seen. Though it also looks like that should not happen (barring out of memory) as both if and else set the value. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:76: inView:(NSView*)controlView; On 2015/05/15 00:09:38, Scott Hess wrote: > If this is only being exposed so that the cell implementation can call it, then > you can either put this method before the calling method, or add it to a private > category, rather than exposing it here. > > A private category would be in the .mm file, and might look like: > > @interface OmniboxPopupCell (private) > // Methods in the category. > @end > > [I was going to ask for a comment, but then realized that it's not really > something anyone else should be calling.] Thanks! I didn't know about that option. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:76: inView:(NSView*)controlView; On 2015/05/15 16:53:56, groby wrote: > On 2015/05/15 00:09:38, Scott Hess wrote: > > If this is only being exposed so that the cell implementation can call it, > then > > you can either put this method before the calling method, or add it to a > private > > category, rather than exposing it here. > > > > A private category would be in the .mm file, and might look like: > > > > @interface OmniboxPopupCell (private) > > // Methods in the category. > > @end > > > > [I was going to ask for a comment, but then realized that it's not really > > something anyone else should be calling.] > > If it's a purely private category in a .mm, I'd suggest an anonymous one - i.e > @interface OmniboxPopupCell () > > Two adavantages - one, implementation of the methods is mandatory, and two, > nobody can later go and re-declare the category elsewhere and still use it. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 16:53:56, groby wrote: > On 2015/05/15 00:09:38, Scott Hess wrote: > > Ack! Chromium style conflicts with my years of Objective-C experience! > > > > Hmm, I think go with it, this is too long otherwise, unless you add a helper. > > This is really rubbing all ObjC senses the wrong way - I'd second the idea of a > helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer will > double take on this :) So I'm kinda guessing what may be so offensive. At first I wondered if you'd prefer a "return nil;" instead of "return self;". I can still move the body to a separate function. I wasn't sure what to name that function, so I indented instead. Maybe initHelperWithMatch? Or is it fine indented? Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:170: [CreateAttributedString(raw_separator, DimTextColor()) retain]); On 2015/05/15 00:09:38, Scott Hess wrote: > Note that scoped_nsobject<> implements operator= to include the retain. So this > could be: > separator_ = [...]; > I am not suggesting that you make that change, just pointing it out. I'm kind > of feeling that a retain() function would make sense, really, to make it clear > that code is saying "Take a reference to this object and keep it." Acknowledged. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:200: answerString += space + textField->text(); On 2015/05/15 00:09:38, Scott Hess wrote: > I find my brain really questioning this. I'd guess it implies that text() is > returning an std::string or a base::string16? If it was: > answerString.append(space).append(text()); > I wouldn't have to think that through, and it would work even if someone changes > text() return, and it also wouldn't create the intermediate object. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:237: // dschuyler about why it's written with swaps and local data. On 2015/05/15 17:28:59, Scott Hess wrote: > On 2015/05/15 16:53:56, groby wrote: > > So kill all this, and in the cell's -copyWithZone just do a copy->cellData_ = > > [cellData_ retain]; > > operator= already implies retain, so either copy->cellData_ = cellData_, or > copy->cellData_.reset([celldata_ retain]). > > The cell's -copyWithZone: actually already does the operator= version, so AFAICT > this method is never called. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth), On 2015/05/15 17:28:59, Scott Hess wrote: > Oooh, maybe give this code a once-over for inappropriate casting. This looks to > me like *contentsMaxWidth should really be a CGFloat, since -drawMatchPart:* is > just casting it back. Apologies that this got to here, I seem to remember the > original review of this code was pretty involved. May we do a separate CL for this? https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:378: // dschuyler about why it's written with swaps and local data. On 2015/05/15 00:09:38, Scott Hess wrote: > Now _this_ code has to keep the crazy. Acknowledged. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:379: base::scoped_nsobject<OmniboxPopupCellData> cellData(nil); On 2015/05/15 00:09:38, Scott Hess wrote: > Though I think the (nil) can be disposed of. It's default to nil. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:380: cellData_.swap(cellData); On 2015/05/15 00:09:38, Scott Hess wrote: > And I would say cellData.swap(cellData_), to make it clear where the reference > ends up. It's exactly the same code in the end, but we (at least I) are tuned > to expect things to end up in the LHS. I wondered about that. One one hand there's seeing that the same operation is done again (argument for keeping them the same). On the other hand there's the LHS consistency. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: array_.reset([[NSMutableArray alloc] init]); On 2015/05/15 00:09:38, Scott Hess wrote: > Use NSArray, here. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:100: [column setDataCell:[[[OmniboxPopupCell alloc] init] autorelease]]; On 2015/05/15 00:09:38, Scott Hess wrote: > This is a case where putting the cell in an scoped_nsobject<> saves you a tiny > fraction of a CPU. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:100: NSMutableArray* array = [NSMutableArray array]; On 2015/05/15 00:09:38, Scott Hess wrote: > I'd also do scoped_nsobject<> of [[NSMutableArray alloc] init] here. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:114: [cellData setImage:image]; On 2015/05/15 17:28:59, Scott Hess wrote: > On 2015/05/15 16:53:56, groby wrote: > > On 2015/05/15 00:09:38, Scott Hess wrote: > > > Should these be individual setters, or should the designated initializer be > > > something like -initWithMatch:rect:image:? > > > > > > Also, should the image be calculated here, or should the cell data calculate > > it > > > from the match? > > > > > > Hmm, and should the cell data even have a rect? Isn't the rect defined by > the > > > cell which the cellData is put into? What would happen if the rect set here > > > conflicted with the rect the cell is being drawn into? > > > > I'd prefer -initWithMatch:image - because that way, we can remove the setter > and > > make clear that yes, cellData is immutable. (See previous comment on > > copyWithZone) > > > > And yes, the rect should be on the cell. > > I don't think it can get to zero setters, because -setMaxMatchContentsWidth: > needs to receive the accumulated-across-the-loop data, and I'm not entirely sure > having separate initializers for with/without-contentsOffset: (plus associated > if/else up here) is worth it. > > AFAICT, since maxMatchContentsWidth_ is only used at display time, it could be a > single attribute of the display cell rather than a duplicated attribute of the > displayed data. But that would just require adding parameters to pass it around > in the display code, so practically I'm not sure it's worthwhile. Done. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:121: contents_offset = [OmniboxPopupCell computeContentsOffset:match]; On 2015/05/15 17:28:59, Scott Hess wrote: > Does this helper still belong in the cell class, or in the data class? Not > really arguing for either way, but having the width calculation just above move > to the data object is suggestive. Making it an instance variable might also > make sense, like: > [cellData computeContentsOffset]; It sounds like this search suggest tail feature is still a work in progress. I'd like to minimize changes to it until Anuj can get further along with it and we can test the changes. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:165: } On 2015/05/15 00:09:38, Scott Hess wrote: > Nevermind my earlier (or later?) comment, this is right. I misunderstood the > suggestion, and am too tired to find my other comment. Acknowledged.
https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 21:52:04, dschuyler wrote: > On 2015/05/15 16:53:56, groby wrote: > > On 2015/05/15 00:09:38, Scott Hess wrote: > > > Ack! Chromium style conflicts with my years of Objective-C experience! > > > > > > Hmm, I think go with it, this is too long otherwise, unless you add a > helper. > > > > This is really rubbing all ObjC senses the wrong way - I'd second the idea of > a > > helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer will > > double take on this :) > > So I'm kinda guessing what may be so offensive. At first I wondered if you'd > prefer a "return nil;" instead of "return self;". Ha, no, there's this whole genre of lore that has grown up over the years around chaining to your superclass' designated initializer. The gist of it WRT Chromium Objective-C is that things should look like: - (instancetype)initWithMyStuff:(MyType)my_stuff { if ((self = [super init])) { // Additional work. } return self; } The previous idiom of separate lines for the [super init] is also fine. But the Chromium style of "Exit early rather than nesting deeply" is directly in conflict with this. I think Rachel's probably correct that this is a case where doing it the old-school way will just keep more Objective-C coder's from having head-exploding issues. What is super amusing about all of this is that the original reasons for +alloc/-init have pretty much gone by the wayside, and the set of classes for which the super call changes self are vanishingly small (and usually doing it for borderline reasons). These days I think most people agree that you should make your special case obvious, like +createMyOptionallySharedInstance rather than try to bury it in -init magic. Also ... nononono to naming the helper -initHelperAnything. -init* is always an initializer. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth), On 2015/05/15 21:52:04, dschuyler wrote: > On 2015/05/15 17:28:59, Scott Hess wrote: > > Oooh, maybe give this code a once-over for inappropriate casting. This looks > to > > me like *contentsMaxWidth should really be a CGFloat, since -drawMatchPart:* > is > > just casting it back. Apologies that this got to here, I seem to remember the > > original review of this code was pretty involved. > > May we do a separate CL for this? If you prefer. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:121: contents_offset = [OmniboxPopupCell computeContentsOffset:match]; On 2015/05/15 21:52:04, dschuyler wrote: > On 2015/05/15 17:28:59, Scott Hess wrote: > > Does this helper still belong in the cell class, or in the data class? Not > > really arguing for either way, but having the width calculation just above > move > > to the data object is suggestive. Making it an instance variable might also > > make sense, like: > > [cellData computeContentsOffset]; > > It sounds like this search suggest tail feature is still a work in progress. > I'd like to minimize changes to it until Anuj can get further along with it and > we can test the changes. In that case I can definitely see not changing from a class method to an instance method, your call as to whether both methods should travel together (both are in the _TAIL case).
https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 22:02:07, Scott Hess wrote: > On 2015/05/15 21:52:04, dschuyler wrote: > > On 2015/05/15 16:53:56, groby wrote: > > > On 2015/05/15 00:09:38, Scott Hess wrote: > > > > Ack! Chromium style conflicts with my years of Objective-C experience! > > > > > > > > Hmm, I think go with it, this is too long otherwise, unless you add a > > helper. > > > > > > This is really rubbing all ObjC senses the wrong way - I'd second the idea > of > > a > > > helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer > will > > > double take on this :) > > > > So I'm kinda guessing what may be so offensive. At first I wondered if you'd > > prefer a "return nil;" instead of "return self;". > > Ha, no, there's this whole genre of lore that has grown up over the years around > chaining to your superclass' designated initializer. The gist of it WRT > Chromium Objective-C is that things should look like: > > - (instancetype)initWithMyStuff:(MyType)my_stuff { > if ((self = [super init])) { > // Additional work. > } > return self; > } > > The previous idiom of separate lines for the [super init] is also fine. But the > Chromium style of "Exit early rather than nesting deeply" is directly in > conflict with this. > > I think Rachel's probably correct that this is a case where doing it the > old-school way will just keep more Objective-C coder's from having > head-exploding issues. > > What is super amusing about all of this is that the original reasons for > +alloc/-init have pretty much gone by the wayside, and the set of classes for > which the super call changes self are vanishingly small (and usually doing it > for borderline reasons). These days I think most people agree that you should > make your special case obvious, like +createMyOptionallySharedInstance rather > than try to bury it in -init magic. > > Also ... nononono to naming the helper -initHelperAnything. -init* is always an > initializer. Yup, what Scott said. What you do in init is a religious debate. The rebellious adherents of the school of NextStep have always written it as if (self = [super init]) and shall forever continue to do so, until the day the earth ends, while the upstarts of the empire of OSX and iOS find little use in it. And in the case of Chromium, we decided to align with the Rebel Alliance instead of the Empire. So if you write it differently, people scanning over the code will simply have their pattern recognizer throw an exception, alerting them to the possible presence of an imperial Star Destroyer. Or something. For a good in-depth reading on this: http://www.cocoawithlove.com/2009/04/what-does-it-mean-when-you-assign-super....
https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 22:02:07, Scott Hess wrote: > On 2015/05/15 21:52:04, dschuyler wrote: > > On 2015/05/15 16:53:56, groby wrote: > > > On 2015/05/15 00:09:38, Scott Hess wrote: > > > > Ack! Chromium style conflicts with my years of Objective-C experience! > > > > > > > > Hmm, I think go with it, this is too long otherwise, unless you add a > > helper. > > > > > > This is really rubbing all ObjC senses the wrong way - I'd second the idea > of > > a > > > helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer > will > > > double take on this :) > > > > So I'm kinda guessing what may be so offensive. At first I wondered if you'd > > prefer a "return nil;" instead of "return self;". > > Ha, no, there's this whole genre of lore that has grown up over the years around > chaining to your superclass' designated initializer. The gist of it WRT > Chromium Objective-C is that things should look like: > > - (instancetype)initWithMyStuff:(MyType)my_stuff { > if ((self = [super init])) { > // Additional work. > } > return self; > } > > The previous idiom of separate lines for the [super init] is also fine. But the > Chromium style of "Exit early rather than nesting deeply" is directly in > conflict with this. > > I think Rachel's probably correct that this is a case where doing it the > old-school way will just keep more Objective-C coder's from having > head-exploding issues. > > What is super amusing about all of this is that the original reasons for > +alloc/-init have pretty much gone by the wayside, and the set of classes for > which the super call changes self are vanishingly small (and usually doing it > for borderline reasons). These days I think most people agree that you should > make your special case obvious, like +createMyOptionallySharedInstance rather > than try to bury it in -init magic. > > Also ... nononono to naming the helper -initHelperAnything. -init* is always an > initializer. Acknowledged. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:165: return self; On 2015/05/15 22:41:33, groby wrote: > On 2015/05/15 22:02:07, Scott Hess wrote: > > On 2015/05/15 21:52:04, dschuyler wrote: > > > On 2015/05/15 16:53:56, groby wrote: > > > > On 2015/05/15 00:09:38, Scott Hess wrote: > > > > > Ack! Chromium style conflicts with my years of Objective-C experience! > > > > > > > > > > Hmm, I think go with it, this is too long otherwise, unless you add a > > > helper. > > > > > > > > This is really rubbing all ObjC senses the wrong way - I'd second the idea > > of > > > a > > > > helper. (Yes, this is purely stylistic - but every single cocoa/ reviewer > > will > > > > double take on this :) > > > > > > So I'm kinda guessing what may be so offensive. At first I wondered if > you'd > > > prefer a "return nil;" instead of "return self;". > > > > Ha, no, there's this whole genre of lore that has grown up over the years > around > > chaining to your superclass' designated initializer. The gist of it WRT > > Chromium Objective-C is that things should look like: > > > > - (instancetype)initWithMyStuff:(MyType)my_stuff { > > if ((self = [super init])) { > > // Additional work. > > } > > return self; > > } > > > > The previous idiom of separate lines for the [super init] is also fine. But > the > > Chromium style of "Exit early rather than nesting deeply" is directly in > > conflict with this. > > > > I think Rachel's probably correct that this is a case where doing it the > > old-school way will just keep more Objective-C coder's from having > > head-exploding issues. > > > > What is super amusing about all of this is that the original reasons for > > +alloc/-init have pretty much gone by the wayside, and the set of classes for > > which the super call changes self are vanishingly small (and usually doing it > > for borderline reasons). These days I think most people agree that you should > > make your special case obvious, like +createMyOptionallySharedInstance rather > > than try to bury it in -init magic. > > > > Also ... nononono to naming the helper -initHelperAnything. -init* is always > an > > initializer. > > Yup, what Scott said. What you do in init is a religious debate. The rebellious > adherents of the school of NextStep have always written it as if (self = [super > init]) and shall forever continue to do so, until the day the earth ends, while > the upstarts of the empire of OSX and iOS find little use in it. > > And in the case of Chromium, we decided to align with the Rebel Alliance instead > of the Empire. > > So if you write it differently, people scanning over the code will simply have > their pattern recognizer throw an exception, alerting them to the possible > presence of an imperial Star Destroyer. Or something. For a good in-depth > reading on this: > http://www.cocoawithlove.com/2009/04/what-does-it-mean-when-you-assign-super.... Acknowledged. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth), On 2015/05/15 22:02:07, Scott Hess wrote: > On 2015/05/15 21:52:04, dschuyler wrote: > > On 2015/05/15 17:28:59, Scott Hess wrote: > > > Oooh, maybe give this code a once-over for inappropriate casting. This > looks > > to > > > me like *contentsMaxWidth should really be a CGFloat, since -drawMatchPart:* > > is > > > just casting it back. Apologies that this got to here, I seem to remember > the > > > original review of this code was pretty involved. > > > > May we do a separate CL for this? > > If you prefer. I made bug 489478 to track this. https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/300001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:121: contents_offset = [OmniboxPopupCell computeContentsOffset:match]; On 2015/05/15 22:02:08, Scott Hess wrote: > On 2015/05/15 21:52:04, dschuyler wrote: > > On 2015/05/15 17:28:59, Scott Hess wrote: > > > Does this helper still belong in the cell class, or in the data class? Not > > > really arguing for either way, but having the width calculation just above > > move > > > to the data object is suggestive. Making it an instance variable might also > > > make sense, like: > > > [cellData computeContentsOffset]; > > > > It sounds like this search suggest tail feature is still a work in progress. > > I'd like to minimize changes to it until Anuj can get further along with it > and > > we can test the changes. > > In that case I can definitely see not changing from a class method to an > instance method, your call as to whether both methods should travel together > (both are in the _TAIL case). I've contacted Anuj about the fact that I'm making changes in this area. Let's keep this as it is for this CL.
Sorry, more... I still think we're not building the data source properly - pretty much all of the feedback would push us closer to having the normal NSTableViewDatasource mechanisms handle things. (Yes, the documentation is crappily incomplete. But we have some examples in Chrome, see e.g. https://code.google.com/p/chromium/codesearch#chromium/src/ui/app_list/cocoa/...) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { NSCell already has a concept of an objectValue - can we use that to store celldata? (And technically, the NSTableView should populate it anyways) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:176: const base::string16& raw_separator = Looks like nobody cares about raw_separator any more... https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:202: DCHECK(!match.answer->second_line().text_fields().empty()); We don't care about type just yet, I assume? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:243: return contents_ ? [contents_ size].width : 0; return [contents_ size].width. See https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Progra... on messages to nil. (Essentially, struct returns have all fields zeroed out) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:400: if (renderRect.size.width != 0) NSWidth(renderRect), please https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: array_.reset([[NSArray alloc] init]); Why reset the array_ to an empty array? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; This still makes me queasy. You are currently not implementing the NSTableViewDataSource API as specified. It's fine to skip setObjectValue for read-only tables, but this technically _needs_ to be implemented. Can you put a breakpoint/LOG in here and see if this is ever called? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:53: [popupCell highlight:(hovered_index_ == rowIndex) hoveredIndex_ :) Which brings up a question - can we have cells that are simultaneously highlighted and hovered? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:211: return [controller_ highlightedRow]; Why not [self selectedRow] ? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:251: observer_->OnMatrixRowSelected(self, row); Do we not want to tell the observer when nothing is selected? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:96: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); Theoretically... What we're building here _is_ essentially the NSTableViewDataSource. Do you think it makes sense to have an initWithMatches: on the data source, and then just set the data source on the NSTableView? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:151: NSIndexSet* indexSet = nil; Since we're only allow single selection, why not move this onto the matrix as -selectRow:
https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/05/20 01:02:30, groby wrote: > NSCell already has a concept of an objectValue - can we use that to store > celldata? (And technically, the NSTableView should populate it anyways) The objectValue requires that the value be parse-able by the NSCell. There is a similar property called representedObject that works well as a cellData_ alternative. Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:176: const base::string16& raw_separator = On 2015/05/20 01:02:30, groby wrote: > Looks like nobody cares about raw_separator any more... I don't follow what ya mean...(?) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:202: DCHECK(!match.answer->second_line().text_fields().empty()); On 2015/05/20 01:02:30, groby wrote: > We don't care about type just yet, I assume? Not for this CL, please. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:243: return contents_ ? [contents_ size].width : 0; On 2015/05/20 01:02:30, groby wrote: > return [contents_ size].width. > See > https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Progra... > > on messages to nil. (Essentially, struct returns have all fields zeroed out) Good to know, thanks! Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:400: if (renderRect.size.width != 0) On 2015/05/20 01:02:30, groby wrote: > NSWidth(renderRect), please Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: array_.reset([[NSArray alloc] init]); On 2015/05/20 01:02:30, groby wrote: > Why reset the array_ to an empty array? Likely because I only just learned about nil as a valid message target. :) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/20 01:02:31, groby wrote: > This still makes me queasy. You are currently not implementing the > NSTableViewDataSource API as specified. > > It's fine to skip setObjectValue for read-only tables, but this technically > _needs_ to be implemented. > > Can you put a breakpoint/LOG in here and see if this is ever called? It is being called. Here's a link to a prior version of this function that returned a value and the discussion about it: https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... Should I change it back to returning a value? https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:53: [popupCell highlight:(hovered_index_ == rowIndex) On 2015/05/20 01:02:30, groby wrote: > hoveredIndex_ :) > > Which brings up a question - can we have cells that are simultaneously > highlighted and hovered? Highlighted and hovered are always in sync (or should be). Selected and highlights can be separate or the same. If they are the same, then the Selected value takes precedence in the GUI. Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:211: return [controller_ highlightedRow]; On 2015/05/20 01:02:31, groby wrote: > Why not [self selectedRow] ? Highlighting is for mouse hovering. Selection is a different thing. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:251: observer_->OnMatrixRowSelected(self, row); On 2015/05/20 01:02:31, groby wrote: > Do we not want to tell the observer when nothing is selected? We keep the last selected item selected. Telling it to deselect would be a departure from the current GUI behavior. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:96: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/20 01:02:31, groby wrote: > Theoretically... > > What we're building here _is_ essentially the NSTableViewDataSource. > > Do you think it makes sense to have an initWithMatches: on the data source, and > then just set the data source on the NSTableView? I've moved the data init into the Controller (which is both the table delegate and the table data source). Does this look better? Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:151: NSIndexSet* indexSet = nil; On 2015/05/20 01:02:31, groby wrote: > Since we're only allow single selection, why not move this onto the matrix as > -selectRow: How about selectRowIndex. Done.
dschuyler@chromium.org changed reviewers: - shrike@chromium.org
Sorry for dragging this out... But we're almost there, I promise! https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/05/21 00:38:39, dschuyler wrote: > On 2015/05/20 01:02:30, groby wrote: > > NSCell already has a concept of an objectValue - can we use that to store > > celldata? (And technically, the NSTableView should populate it anyways) > > The objectValue requires that the value be parse-able by the NSCell. There is a > similar property called representedObject that works well as a cellData_ > alternative. > > Done. You'd _think_ it has to be parsable, but it doesn't :) (The formatter can be nil, and the world is still fine) The objectValue must, however, obey the NSCopying protocol https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:176: const base::string16& raw_separator = On 2015/05/21 00:38:39, dschuyler wrote: > On 2015/05/20 01:02:30, groby wrote: > > Looks like nobody cares about raw_separator any more... > > I don't follow what ya mean...(?) Never mind, my brain mis-parsed the next line. Either way, it shouldn't be a reference. GetStringUTF16 returns a value, not a reference. (The C++ standard bails you out by demanding the compiler extend the lifetime, but please don't :) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:202: DCHECK(!match.answer->second_line().text_fields().empty()); On 2015/05/21 00:38:39, dschuyler wrote: > On 2015/05/20 01:02:30, groby wrote: > > We don't care about type just yet, I assume? > > Not for this CL, please. Acknowledged. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/21 00:38:39, dschuyler wrote: > On 2015/05/20 01:02:31, groby wrote: > > This still makes me queasy. You are currently not implementing the > > NSTableViewDataSource API as specified. > > > > It's fine to skip setObjectValue for read-only tables, but this technically > > _needs_ to be implemented. > > > > Can you put a breakpoint/LOG in here and see if this is ever called? > > It is being called. > > Here's a link to a prior version of this function that returned a value and the > discussion about it: > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > Should I change it back to returning a value? No, we should try to understand what's actually going on first :) (Seriously. While Cocoa is mysterious, please make sure you understand why things are there/need to be done. It'll make it much less fragile) Implementing the data source is technically enough to display a cell-based NSTableView, as per docs. (Everything on NSTableViewDelegate is optional customization) So, where is the value from the datasource communicated to the cell? The docs are unfortunately not very clear on the subject, but the fact that this is objectValueForTableColumn means likely that this is an objectValue for an NSCell. But don't trust me, verify for yourself. print out callstacks from here and from your cell's setObjectValue: Better, turn on prints of all messages as sent around this, via instrumentObjcMessageSends. (See this article on debugging message flow: http://www.dribin.org/dave/blog/archives/2006/04/22/tracing_objc/ And read the technote on debugging, which will change your life: https://developer.apple.com/library/mac/technotes/tn2124/_index.html) You'll see that as the NSTableView displays individual cells, it will call this function to get an objectValue, and then set it on the appropriate cell. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:359: // The default NSButtonCell drawing leaves the image flush left and Comment doesn't apply any more - it's just an NSCell now. (Also - star button and autocomplete field didn't apply.) If I may make a suggestion, you might want to clean up comments when you copied code, so this doesn't bit in reviews :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:376: [self representedObject]); No need to scope - representedObject (and objectValue) retain their data. Just pass [self objectValue] to drawMatchWithFrame:inCell:inView https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); Why not keep it directly in array_? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { Please don't perpetuate ii :) Best, don't even loop manually. AutocompleteResult conforms to STL's iterator conventions, so for (const AutocompleteMatch& match : result) { will do the trick. Plus, potentially a removeObjectAtIndex:0 at the end if we hide the top match. Yes, we pay one extra conversion, but it makes the code more readable. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: NSImage* image = popupView.ImageForMatch(match); Bleh. I hate we have to pass the popupView. I wonder if we need to hoist the datasource out. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:45: [array addObject:cellData]; You _could_ just move the alloc/initWithMatch call in here and skip the scoped temporary. (Yes, deeply nested message chains are common in Cocoa :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:56: for (size_t ii = 0; ii < rows; ++ii) { for (OmniboxPopupCellData* cellData : array) [cellData setMax.... https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:112: OmniboxPopupCellData* cellData = [array_ objectAtIndex:row]; chaining methods would be preferred - no need to have temps. return [[array_ objectAtIndex:row] rowHeight]; https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:113: return [cellData rowHeight]; Just a general note on tables, no need to implement: If the data source were a separate class, you'd invoke -preparedCellAtColumn:row: to get a cell populated with the appropriate data. That method, by the way, is where the cell's objectValue is set from the datasource. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:133: [[OmniboxPopupCell alloc] init]); Again, skip the scoped temp and chain methods. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:42: [matrix_ addTableColumn:column]; Why add another table column? Didn't -initWithObserver already do that? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:45: for (size_t ii = 0; ii < 3; ++ii) { Please, please, please: No ii :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); chain methods :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:53: NSRect table_frame = NSZeroRect; NSMakeRect(0, 0, testWidth, NSHeight([matrix_ frame]); In general: Do we need a setFrame here?
https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/21 03:01:48, groby wrote: > On 2015/05/21 00:38:39, dschuyler wrote: > > On 2015/05/20 01:02:31, groby wrote: > > > This still makes me queasy. You are currently not implementing the > > > NSTableViewDataSource API as specified. > > > > > > It's fine to skip setObjectValue for read-only tables, but this technically > > > _needs_ to be implemented. > > > > > > Can you put a breakpoint/LOG in here and see if this is ever called? > > > > It is being called. > > > > Here's a link to a prior version of this function that returned a value and > the > > discussion about it: > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > > > Should I change it back to returning a value? > > No, we should try to understand what's actually going on first :) (Seriously. > While Cocoa is mysterious, please make sure you understand why things are > there/need to be done. It'll make it much less fragile) > > Implementing the data source is technically enough to display a cell-based > NSTableView, as per docs. (Everything on NSTableViewDelegate is optional > customization) > > So, where is the value from the datasource communicated to the cell? The docs > are unfortunately not very clear on the subject, but the fact that this is > objectValueForTableColumn means likely that this is an objectValue for an > NSCell. > > But don't trust me, verify for yourself. print out callstacks from here and from > your cell's setObjectValue: > > Better, turn on prints of all messages as sent around this, via > instrumentObjcMessageSends. (See this article on debugging message flow: > http://www.dribin.org/dave/blog/archives/2006/04/22/tracing_objc/ > And read the technote on debugging, which will change your life: > https://developer.apple.com/library/mac/technotes/tn2124/_index.html) > > You'll see that as the NSTableView displays individual cells, it will call this > function to get an objectValue, and then set it on the appropriate cell. > > > Something I have often done is created a distinct Xcode project and experimented over there to figure out what's up in a non-Chrome environment. The Edit/Compile/Run loop is about infinity faster, so you can nail something down in 15 minutes that might take a long grind in a Chrome context. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/21 03:01:48, groby wrote: > Please don't perpetuate ii :) Yeah, that's some ancient habit of mine which has since been ground away. ii and jj are way easier to do search/replace on, but it's the kind of thing you need in the style guide to make sense, and most people just think it's weird.
https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:41: - (id)initWithMatch:(const AutocompleteMatch&)match image:(NSImage*)image; Instead of (id) use (instancetype). The reason is subtle, but the gist of it is that (id) is entirely unchecked, it can be any Objective-C object including objects which are instances from a different class hierarchy, while (instancetype) is closer to the intended isa relationship. I think this advice is only applicable to designated initializers. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:45: inView:(NSView*)controlView; This can probably be -drawWithFrame:inCell:inView:. There's not another kind of draw to distinguish things from, and none of the other instance information is expressed into the method signature. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:47: - (CGFloat)rowHeight; This one could use a comment, since there's not an obvious instance-variable comment to refer to. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:59: // handle hover versus selected. This comment seems inadequate, since it does more than that. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:189: // contents so we force the directionality. Reformat comment. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:247: return [image_ size].height + kCellHeightAdjust; I realize that the current version doesn't have the part which will do variable height, but this seems dubious. I think the closest to the previous version would be [super cellSize].height + kCellHeightAdjust, though that may differ due to the reparenting. Is the image size constant? I'd be happy with a constant. It's arbitrary, but that's one less bit of arbitrary. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:354: // The representedObject is set to nil in the copy. What did they do, put _all_ of the special edge cases in NSCell? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:376: [self representedObject]); On 2015/05/21 03:01:48, groby wrote: > No need to scope - representedObject (and objectValue) retain their data. Just > pass [self objectValue] to drawMatchWithFrame:inCell:inView Scoping is wrong, because -representedObject is not adding an additional reference for scoped_nsobject<> to own. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:394: if (NSWidth(renderRect) != 0) I'd say > 0.0. Just because I'm that paranoid. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @end This I'm unsure of. It's comparable to defining a C signature and calling it, it works fine, it just means that someone over editing the object won't know about it until runtime crashes (if they're lucky). Rachel may have a stronger opinion, but I have a weak opinion that this should be in the header, something like: @interface OmniboxPopupCellData (TestingAPI) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: DCHECK_GT(rows, 0U); IMHO this would be better as: DCHECK_GT(result.size(), start_match); https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/21 03:01:48, groby wrote: > Why not keep it directly in array_? array_ is NSArray. Which makes me wonder if array_.reset([array copy]). I can't think of any strong reason against array_ being NSMutableArray. It's less correct in a dimension which is fairly irrelevant. Then again this is kind of a rathole to go down. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:45: [array addObject:cellData]; On 2015/05/21 03:01:48, groby wrote: > You _could_ just move the alloc/initWithMatch call in here and skip the scoped > temporary. (Yes, deeply nested message chains are common in Cocoa :) Someone needs to own the +alloc ref, though. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, On 2015/05/21 03:01:48, groby wrote: > So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? Yeah, this is a thing we ground on about in the original CL. You can either have zero or one set of results like this. When you have one, they are in a block, and the prefix is elided so that you can see the grouping visually. I'm still not entirely convinced it wouldn't be better as a distinct loop, but I suspect it's messy either way. [I think that was accurate. Multiple cells needed to align something.] https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: if (contents_offset < 0.0f) { Drop the {} here. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:65: - (id)initWithArray:(NSArray*)array { instancetype. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:133: [[OmniboxPopupCell alloc] init]); On 2015/05/21 03:01:48, groby wrote: > Again, skip the scoped temp and chain methods. I think this one also leaves an additional ref unless you have the scoper or autorelease. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end Same as my other comment, test-only API in the header, with the interface marked. And instancetype. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/21 03:01:48, groby wrote: > chain methods :) For tests, I'm more lenient about -autorelease, as the -setDataCell: call above. Little bit more towards the easy-to-read side of the balance versus the basically-free-performance side. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:51: initWithArray:array]]; I believe the only refs to OPTController after this line are weak references. You need someone to own it. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:53: NSRect table_frame = NSZeroRect; On 2015/05/21 03:01:48, groby wrote: > NSMakeRect(0, 0, testWidth, NSHeight([matrix_ frame]); > > In general: Do we need a setFrame here? I'd not bother defining testWidth unless you're using it multiple times, since I think its meaning is obvious from context. And if you are defining it, it should be const CGFloat kTestWidth, probably. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (left): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:247: return; Did I already mention that this looks like something which is here because <reasons>? I wish I knew what the reasons were. I suspect there might be cases where the user is typing and the view updates while animating, and it does something weird. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:95: popupView:*this]]; I don't think anyone has the owning reference to OPTController after this, so it will eventually leak. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:278: const AutocompleteMatch& match) const { I was wondering earlier if this could just be pulled down to the client code, but from here it looks like -initWithMatchResults:popupView: either needs |this| to bridge, or a direct ref to |model_|, or some sort of new image-finder-for-match interface. Not sure the latter is worth the while.
https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:354: // The representedObject is set to nil in the copy. On 2015/05/21 20:40:27, Scott Hess wrote: > What did they do, put _all_ of the special edge cases in NSCell? Hey, at least this one is documented. (Under representedObject, not copyWithZone - but beggars can't be choosers :) Either way, objectValue all the way, and this isn't a problem any more. If you do insist on keeping representedObject, you'll want to copyWithZone it though, not just retain it. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:394: if (NSWidth(renderRect) != 0) On 2015/05/21 20:40:26, Scott Hess wrote: > I'd say > 0.0. Just because I'm that paranoid. Let's be properly paranoid and say !NSIsEmptyRect(renderRect)) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @end On 2015/05/21 20:40:27, Scott Hess wrote: > This I'm unsure of. It's comparable to defining a C signature and calling it, > it works fine, it just means that someone over editing the object won't know > about it until runtime crashes (if they're lucky). Rachel may have a stronger > opinion, but I have a weak opinion that this should be in the header, something > like: > > @interface OmniboxPopupCellData (TestingAPI) I'm fine with that crash, since it crashes _tests_ :) But as-is, this is indeed not what I'm looking for - I'd like both test interface *and* implementation to live in test files. The reason being that we pay a memory cost if we just bundle testing APIs into the executable. Yes, it's small, but it adds up. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:45: [array addObject:cellData]; On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > You _could_ just move the alloc/initWithMatch call in here and skip the scoped > > temporary. (Yes, deeply nested message chains are common in Cocoa :) > > Someone needs to own the +alloc ref, though. Yep: [array addObject:[[[OmniboxPopupCellData alloc] initWithMatch: match image:image] autorelease]]; Ultimately, I'm fine either way with a _slight_ preference to avoiding temp objects. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:133: [[OmniboxPopupCell alloc] init]); On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > Again, skip the scoped temp and chain methods. > > I think this one also leaves an additional ref unless you have the scoper or > autorelease. Acknowledged.
https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @end On 2015/05/22 05:03:07, groby wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > This I'm unsure of. It's comparable to defining a C signature and calling it, > > it works fine, it just means that someone over editing the object won't know > > about it until runtime crashes (if they're lucky). Rachel may have a stronger > > opinion, but I have a weak opinion that this should be in the header, > something > > like: > > > > @interface OmniboxPopupCellData (TestingAPI) > > I'm fine with that crash, since it crashes _tests_ :) > > But as-is, this is indeed not what I'm looking for - I'd like both test > interface *and* implementation to live in test files. The reason being that we > pay a memory cost if we just bundle testing APIs into the executable. Yes, it's > small, but it adds up. > > Oh, yes, that's true. If the implementation is only there for tests to mess around with things, then by all means pull it into the test code. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:45: [array addObject:cellData]; On 2015/05/22 05:03:07, groby wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > You _could_ just move the alloc/initWithMatch call in here and skip the > scoped > > > temporary. (Yes, deeply nested message chains are common in Cocoa :) > > > > Someone needs to own the +alloc ref, though. > > Yep: > > [array addObject:[[[OmniboxPopupCellData alloc] initWithMatch: match > image:image] autorelease]]; > > Ultimately, I'm fine either way with a _slight_ preference to avoiding temp > objects. I think that means you can do what you wish, either use a scoped_nsobject<> or autorelease. I think it's six of one and half-a-dozen of the other, in the end, where my earlier "tiny bit of performance" argument gets offset by "looks more like Cocoa" - so I guess experiment then decide, so that you can be consistent in your code so that readers aren't getting confused.
I'm going OOT starting tomorrow, and hope to be out of reach of shess@chromium.org . So groby is in charge! I really hope the review isn't still in play when I get back :-).
WIP on the objectValue vs representedObject discussion. This is an interim patch trying to tie up the other bits before refining the objectValue stuff. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/05/21 03:01:47, groby wrote: > On 2015/05/21 00:38:39, dschuyler wrote: > > On 2015/05/20 01:02:30, groby wrote: > > > NSCell already has a concept of an objectValue - can we use that to store > > > celldata? (And technically, the NSTableView should populate it anyways) > > > > The objectValue requires that the value be parse-able by the NSCell. There is > a > > similar property called representedObject that works well as a cellData_ > > alternative. > > > > Done. > > You'd _think_ it has to be parsable, but it doesn't :) (The formatter can be > nil, and the world is still fine) > > The objectValue must, however, obey the NSCopying protocol > That makes sense. Should I change it from representedObject to objectValue? I kinda feel like representedObject is more representative of the relationship. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:176: const base::string16& raw_separator = On 2015/05/21 03:01:47, groby wrote: > On 2015/05/21 00:38:39, dschuyler wrote: > > On 2015/05/20 01:02:30, groby wrote: > > > Looks like nobody cares about raw_separator any more... > > > > I don't follow what ya mean...(?) > > Never mind, my brain mis-parsed the next line. > > Either way, it shouldn't be a reference. GetStringUTF16 returns a value, not a > reference. (The C++ standard bails you out by demanding the compiler extend the > lifetime, but please don't :) Done. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/21 03:01:48, groby wrote: > On 2015/05/21 00:38:39, dschuyler wrote: > > On 2015/05/20 01:02:31, groby wrote: > > > This still makes me queasy. You are currently not implementing the > > > NSTableViewDataSource API as specified. > > > > > > It's fine to skip setObjectValue for read-only tables, but this technically > > > _needs_ to be implemented. > > > > > > Can you put a breakpoint/LOG in here and see if this is ever called? > > > > It is being called. > > > > Here's a link to a prior version of this function that returned a value and > the > > discussion about it: > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > > > Should I change it back to returning a value? > > No, we should try to understand what's actually going on first :) (Seriously. > While Cocoa is mysterious, please make sure you understand why things are > there/need to be done. It'll make it much less fragile) > > Implementing the data source is technically enough to display a cell-based > NSTableView, as per docs. (Everything on NSTableViewDelegate is optional > customization) > > So, where is the value from the datasource communicated to the cell? The docs > are unfortunately not very clear on the subject, but the fact that this is > objectValueForTableColumn means likely that this is an objectValue for an > NSCell. > > But don't trust me, verify for yourself. print out callstacks from here and from > your cell's setObjectValue: > > Better, turn on prints of all messages as sent around this, via > instrumentObjcMessageSends. (See this article on debugging message flow: > http://www.dribin.org/dave/blog/archives/2006/04/22/tracing_objc/ > And read the technote on debugging, which will change your life: > https://developer.apple.com/library/mac/technotes/tn2124/_index.html) > > You'll see that as the NSTableView displays individual cells, it will call this > function to get an objectValue, and then set it on the appropriate cell. > > > I'll look into this further. I'm going to put an interim patch in without this. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:41: - (id)initWithMatch:(const AutocompleteMatch&)match image:(NSImage*)image; On 2015/05/21 20:40:26, Scott Hess wrote: > Instead of (id) use (instancetype). The reason is subtle, but the gist of it is > that (id) is entirely unchecked, it can be any Objective-C object including > objects which are instances from a different class hierarchy, while > (instancetype) is closer to the intended isa relationship. > > I think this advice is only applicable to designated initializers. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:45: inView:(NSView*)controlView; On 2015/05/21 20:40:26, Scott Hess wrote: > This can probably be -drawWithFrame:inCell:inView:. There's not another kind of > draw to distinguish things from, and none of the other instance information is > expressed into the method signature. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:59: // handle hover versus selected. On 2015/05/21 20:40:26, Scott Hess wrote: > This comment seems inadequate, since it does more than that. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:189: // contents so we force the directionality. On 2015/05/21 20:40:26, Scott Hess wrote: > Reformat comment. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:247: return [image_ size].height + kCellHeightAdjust; On 2015/05/21 20:40:26, Scott Hess wrote: > I realize that the current version doesn't have the part which will do variable > height, but this seems dubious. I think the closest to the previous version > would be [super cellSize].height + kCellHeightAdjust, though that may differ due > to the reparenting. > > Is the image size constant? I'd be happy with a constant. It's arbitrary, but > that's one less bit of arbitrary. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:354: // The representedObject is set to nil in the copy. On 2015/05/21 20:40:27, Scott Hess wrote: > What did they do, put _all_ of the special edge cases in NSCell? Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:354: // The representedObject is set to nil in the copy. On 2015/05/22 05:03:07, groby wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > What did they do, put _all_ of the special edge cases in NSCell? > > Hey, at least this one is documented. (Under representedObject, not copyWithZone > - but beggars can't be choosers :) > > Either way, objectValue all the way, and this isn't a problem any more. If you > do insist on keeping representedObject, you'll want to copyWithZone it though, > not just retain it. I'm looking into the objectValue vs representedObject stuff (still a wip). https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:359: // The default NSButtonCell drawing leaves the image flush left and On 2015/05/21 03:01:48, groby wrote: > Comment doesn't apply any more - it's just an NSCell now. (Also - star button > and autocomplete field didn't apply.) > > If I may make a suggestion, you might want to clean up comments when you copied > code, so this doesn't bit in reviews :) Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:376: [self representedObject]); On 2015/05/21 03:01:48, groby wrote: > No need to scope - representedObject (and objectValue) retain their data. Just > pass [self objectValue] to drawMatchWithFrame:inCell:inView Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:376: [self representedObject]); On 2015/05/21 20:40:26, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > No need to scope - representedObject (and objectValue) retain their data. Just > > pass [self objectValue] to drawMatchWithFrame:inCell:inView > > Scoping is wrong, because -representedObject is not adding an additional > reference for scoped_nsobject<> to own. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:394: if (NSWidth(renderRect) != 0) On 2015/05/21 20:40:26, Scott Hess wrote: > I'd say > 0.0. Just because I'm that paranoid. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @end On 2015/05/21 20:40:27, Scott Hess wrote: > This I'm unsure of. It's comparable to defining a C signature and calling it, > it works fine, it just means that someone over editing the object won't know > about it until runtime crashes (if they're lucky). Rachel may have a stronger > opinion, but I have a weak opinion that this should be in the header, something > like: > > @interface OmniboxPopupCellData (TestingAPI) Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:36: DCHECK_GT(rows, 0U); On 2015/05/21 20:40:27, Scott Hess wrote: > IMHO this would be better as: > DCHECK_GT(result.size(), start_match); Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/21 03:01:48, groby wrote: > Why not keep it directly in array_? For reasons Scott gives below. :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > Why not keep it directly in array_? > > array_ is NSArray. Which makes me wonder if array_.reset([array copy]). I > can't think of any strong reason against array_ being NSMutableArray. It's less > correct in a dimension which is fairly irrelevant. Then again this is kind of a > rathole to go down. If there are good reasons to choose style A or B without a clear winner, I'm inclined to stay with whichever way is currently written. Of course, it's up to you two :) [to paraphrase a friend of mine]: Is one way more betterer than the other? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/21 03:01:48, groby wrote: > Please don't perpetuate ii :) Best, don't even loop manually. > > AutocompleteResult conforms to STL's iterator conventions, so > for (const AutocompleteMatch& match : result) { > > will do the trick. Plus, potentially a removeObjectAtIndex:0 at the end if we > hide the top match. Yes, we pay one extra conversion, but it makes the code more > readable. The <should hide top match> stuff is a discontinued experiment afaik. Peter had asked if I wanted to remove it, but I was planning to minimize this CL and do it later. It can be done now if it makes this CL simpler. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/21 04:46:36, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > Please don't perpetuate ii :) > > Yeah, that's some ancient habit of mine which has since been ground away. ii > and jj are way easier to do search/replace on, but it's the kind of thing you > need in the style guide to make sense, and most people just think it's weird. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: NSImage* image = popupView.ImageForMatch(match); On 2015/05/21 03:01:48, groby wrote: > Bleh. I hate we have to pass the popupView. I wonder if we need to hoist the > datasource out. Which direction is the right way to go for this particular CL? Could we alter that in a later CL? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:45: [array addObject:cellData]; On 2015/05/22 05:17:58, Scott Hess (OOO to 5-28) wrote: > On 2015/05/22 05:03:07, groby wrote: > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > On 2015/05/21 03:01:48, groby wrote: > > > > You _could_ just move the alloc/initWithMatch call in here and skip the > > scoped > > > > temporary. (Yes, deeply nested message chains are common in Cocoa :) > > > > > > Someone needs to own the +alloc ref, though. > > > > Yep: > > > > [array addObject:[[[OmniboxPopupCellData alloc] initWithMatch: match > > image:image] autorelease]]; > > > > Ultimately, I'm fine either way with a _slight_ preference to avoiding temp > > objects. > > I think that means you can do what you wish, either use a scoped_nsobject<> or > autorelease. I think it's six of one and half-a-dozen of the other, in the end, > where my earlier "tiny bit of performance" argument gets offset by "looks more > like Cocoa" - so I guess experiment then decide, so that you can be consistent > in your code so that readers aren't getting confused. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, On 2015/05/21 03:01:48, groby wrote: > So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? > > Yeah, this is a thing we ground on about in the original CL. You can either > have zero or one set of results like this. When you have one, they are in a > block, and the prefix is elided so that you can see the grouping visually. I'm > still not entirely convinced it wouldn't be better as a distinct loop, but I > suspect it's messy either way. > > [I think that was accurate. Multiple cells needed to align something.] Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? > > Yeah, this is a thing we ground on about in the original CL. You can either > have zero or one set of results like this. When you have one, they are in a > block, and the prefix is elided so that you can see the grouping visually. I'm > still not entirely convinced it wouldn't be better as a distinct loop, but I > suspect it's messy either way. > > [I think that was accurate. Multiple cells needed to align something.] I'd like to leave the TAIL stuff unchanged until Anuj can get involved. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:49: if (contents_offset < 0.0f) { On 2015/05/21 20:40:27, Scott Hess wrote: > Drop the {} here. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:56: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/21 03:01:48, groby wrote: > for (OmniboxPopupCellData* cellData : array) > [cellData setMax.... > Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:65: - (id)initWithArray:(NSArray*)array { On 2015/05/21 20:40:27, Scott Hess wrote: > instancetype. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:112: OmniboxPopupCellData* cellData = [array_ objectAtIndex:row]; On 2015/05/21 03:01:48, groby wrote: > chaining methods would be preferred - no need to have temps. > return [[array_ objectAtIndex:row] rowHeight]; Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:113: return [cellData rowHeight]; On 2015/05/21 03:01:48, groby wrote: > Just a general note on tables, no need to implement: > > If the data source were a separate class, you'd invoke > -preparedCellAtColumn:row: to get a cell populated with the appropriate data. > > That method, by the way, is where the cell's objectValue is set from the > datasource. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:133: [[OmniboxPopupCell alloc] init]); On 2015/05/21 03:01:48, groby wrote: > Again, skip the scoped temp and chain methods. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:133: [[OmniboxPopupCell alloc] init]); On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > Again, skip the scoped temp and chain methods. > > I think this one also leaves an additional ref unless you have the scoper or > autorelease. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end On 2015/05/21 20:40:27, Scott Hess wrote: > Same as my other comment, test-only API in the header, with the interface > marked. And instancetype. I made the change for instancetype. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:42: [matrix_ addTableColumn:column]; On 2015/05/21 03:01:48, groby wrote: > Why add another table column? Didn't -initWithObserver already do that? Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:45: for (size_t ii = 0; ii < 3; ++ii) { On 2015/05/21 03:01:48, groby wrote: > Please, please, please: No ii :) Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > chain methods :) > > For tests, I'm more lenient about -autorelease, as the -setDataCell: call above. > Little bit more towards the easy-to-read side of the balance versus the > basically-free-performance side. I'd like to keep the reference counting correct. Is it better to have the scoped object or the autorelease? https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:51: initWithArray:array]]; On 2015/05/21 20:40:27, Scott Hess wrote: > I believe the only refs to OPTController after this line are weak references. > You need someone to own it. Thanks. I totally missed that. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:53: NSRect table_frame = NSZeroRect; On 2015/05/21 03:01:48, groby wrote: > NSMakeRect(0, 0, testWidth, NSHeight([matrix_ frame]); > > In general: Do we need a setFrame here? Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:53: NSRect table_frame = NSZeroRect; On 2015/05/21 20:40:27, Scott Hess wrote: > On 2015/05/21 03:01:48, groby wrote: > > NSMakeRect(0, 0, testWidth, NSHeight([matrix_ frame]); > > > > In general: Do we need a setFrame here? Not needed any longer. > > I'd not bother defining testWidth unless you're using it multiple times, since I > think its meaning is obvious from context. And if you are defining it, it > should be const CGFloat kTestWidth, probably. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (left): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:247: return; On 2015/05/21 20:40:27, Scott Hess (OOO to 5-28) wrote: > Did I already mention that this looks like something which is here because > <reasons>? I wish I knew what the reasons were. I suspect there might be cases > where the user is typing and the view updates while animating, and it does > something weird. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:95: popupView:*this]]; On 2015/05/21 20:40:27, Scott Hess wrote: > I don't think anyone has the owning reference to OPTController after this, so it > will eventually leak. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:278: const AutocompleteMatch& match) const { On 2015/05/21 20:40:27, Scott Hess wrote: > I was wondering earlier if this could just be pulled down to the client code, > but from here it looks like -initWithMatchResults:popupView: either needs |this| > to bridge, or a direct ref to |model_|, or some sort of new > image-finder-for-match interface. Not sure the latter is worth the while. I wondered about the same. In the scope of 'this is a CL to convert from NSMatrix to NSTableView' should the image for match change?
Waiting for -objectValue for a full pass :) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/05/26 18:40:19, dschuyler wrote: > On 2015/05/21 03:01:47, groby wrote: > > On 2015/05/21 00:38:39, dschuyler wrote: > > > On 2015/05/20 01:02:30, groby wrote: > > > > NSCell already has a concept of an objectValue - can we use that to store > > > > celldata? (And technically, the NSTableView should populate it anyways) > > > > > > The objectValue requires that the value be parse-able by the NSCell. There > is > > a > > > similar property called representedObject that works well as a cellData_ > > > alternative. > > > > > > Done. > > > > You'd _think_ it has to be parsable, but it doesn't :) (The formatter can be > > nil, and the world is still fine) > > > > The objectValue must, however, obey the NSCopying protocol > > > > That makes sense. Should I change it from representedObject to objectValue? I > kinda feel like representedObject is more representative of the relationship. Yes, please. -representedObject is the wrong choice. Quoth the docs: "This feature is solely for the developer’s convenience. The cell itself does not use the represented object, except to archive and restore it." objectValue is the actual value displayed by the object. (Yes, there's some room for semantics - but the general expectation is that if I change objectValue, the display changes. If I change representedValue, nobody cares) (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Contro...) https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/26 18:40:19, dschuyler wrote: > On 2015/05/21 03:01:48, groby wrote: > > On 2015/05/21 00:38:39, dschuyler wrote: > > > On 2015/05/20 01:02:31, groby wrote: > > > > This still makes me queasy. You are currently not implementing the > > > > NSTableViewDataSource API as specified. > > > > > > > > It's fine to skip setObjectValue for read-only tables, but this > technically > > > > _needs_ to be implemented. > > > > > > > > Can you put a breakpoint/LOG in here and see if this is ever called? > > > > > > It is being called. > > > > > > Here's a link to a prior version of this function that returned a value and > > the > > > discussion about it: > > > > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > > > > > Should I change it back to returning a value? > > > > No, we should try to understand what's actually going on first :) (Seriously. > > While Cocoa is mysterious, please make sure you understand why things are > > there/need to be done. It'll make it much less fragile) > > > > Implementing the data source is technically enough to display a cell-based > > NSTableView, as per docs. (Everything on NSTableViewDelegate is optional > > customization) > > > > So, where is the value from the datasource communicated to the cell? The docs > > are unfortunately not very clear on the subject, but the fact that this is > > objectValueForTableColumn means likely that this is an objectValue for an > > NSCell. > > > > But don't trust me, verify for yourself. print out callstacks from here and > from > > your cell's setObjectValue: > > > > Better, turn on prints of all messages as sent around this, via > > instrumentObjcMessageSends. (See this article on debugging message flow: > > http://www.dribin.org/dave/blog/archives/2006/04/22/tracing_objc/ > > And read the technote on debugging, which will change your life: > > https://developer.apple.com/library/mac/technotes/tn2124/_index.html) > > > > You'll see that as the NSTableView displays individual cells, it will call > this > > function to get an objectValue, and then set it on the appropriate cell. > > > > > > > > I'll look into this further. I'm going to put an interim patch in without this. Waiting for the final patch before I do a full review, then. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/26 18:40:20, dschuyler wrote: > On 2015/05/21 03:01:48, groby wrote: > > Why not keep it directly in array_? > > For reasons Scott gives below. :) Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/26 18:40:20, dschuyler wrote: > On 2015/05/21 03:01:48, groby wrote: > > Please don't perpetuate ii :) Best, don't even loop manually. > > > > AutocompleteResult conforms to STL's iterator conventions, so > > for (const AutocompleteMatch& match : result) { > > > > will do the trick. Plus, potentially a removeObjectAtIndex:0 at the end if we > > hide the top match. Yes, we pay one extra conversion, but it makes the code > more > > readable. > > The <should hide top match> stuff is a discontinued experiment afaik. Peter had > asked if I wanted to remove it, but I was planning to minimize this CL and do it > later. It can be done now if it makes this CL simpler. > > Done. If you can do that as a prior CL and rebase this CL onto that cleanup, much appreciated. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: NSImage* image = popupView.ImageForMatch(match); On 2015/05/26 18:40:21, dschuyler wrote: > On 2015/05/21 03:01:48, groby wrote: > > Bleh. I hate we have to pass the popupView. I wonder if we need to hoist the > > datasource out. > > Which direction is the right way to go for this particular CL? > Could we alter that in a later CL? Yes, I think that's fine. It's not perfect, but it's OK (IMHO). Please do add a TODO/follow-up bug, though. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:47: max_match_contents_width = std::max(max_match_contents_width, On 2015/05/26 18:40:21, dschuyler wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > So max_match_contents_width stays 0 unless you have a SEARCH_SUGGEST_TAIL? > > > > Yeah, this is a thing we ground on about in the original CL. You can either > > have zero or one set of results like this. When you have one, they are in a > > block, and the prefix is elided so that you can see the grouping visually. > I'm > > still not entirely convinced it wouldn't be better as a distinct loop, but I > > suspect it's messy either way. > > > > [I think that was accurate. Multiple cells needed to align something.] > > I'd like to leave the TAIL stuff unchanged until Anuj can get involved. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/26 18:40:21, dschuyler wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > chain methods :) > > > > For tests, I'm more lenient about -autorelease, as the -setDataCell: call > above. > > Little bit more towards the easy-to-read side of the balance versus the > > basically-free-performance side. > > I'd like to keep the reference counting correct. > Is it better to have the scoped object or the autorelease? It's a minimal cost, so I'm not too worried. I lean slightly towards the chained methods (because Cocoa), but if you prefer scoped_nsobject, there's enough code that does the same. Dealer's choice :) https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:278: const AutocompleteMatch& match) const { On 2015/05/26 18:40:21, dschuyler wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > I was wondering earlier if this could just be pulled down to the client code, > > but from here it looks like -initWithMatchResults:popupView: either needs > |this| > > to bridge, or a direct ref to |model_|, or some sort of new > > image-finder-for-match interface. Not sure the latter is worth the while. > > I wondered about the same. In the scope of 'this is a CL to convert from > NSMatrix to NSTableView' should the image for match change? I think we've heaped on enough change :) Follow-up bug, please?
https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:19, dschuyler wrote: > > On 2015/05/21 03:01:47, groby wrote: > > > On 2015/05/21 00:38:39, dschuyler wrote: > > > > On 2015/05/20 01:02:30, groby wrote: > > > > > NSCell already has a concept of an objectValue - can we use that to > store > > > > > celldata? (And technically, the NSTableView should populate it anyways) > > > > > > > > The objectValue requires that the value be parse-able by the NSCell. > There > > is > > > a > > > > similar property called representedObject that works well as a cellData_ > > > > alternative. > > > > > > > > Done. > > > > > > You'd _think_ it has to be parsable, but it doesn't :) (The formatter can be > > > nil, and the world is still fine) > > > > > > The objectValue must, however, obey the NSCopying protocol > > > > > > > That makes sense. Should I change it from representedObject to objectValue? > I > > kinda feel like representedObject is more representative of the relationship. > > Yes, please. -representedObject is the wrong choice. Quoth the docs: "This > feature is solely for the developer’s convenience. The cell itself does not use > the represented object, except to archive and restore it." > > objectValue is the actual value displayed by the object. (Yes, there's some room > for semantics - but the general expectation is that if I change objectValue, the > display changes. If I change representedValue, nobody cares) > > (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Contro...) >"This feature is solely for the developer’s convenience." I love it when stuff is done for my convenience. Acknowledged. https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/340001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:35: return nil; On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:19, dschuyler wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > On 2015/05/21 00:38:39, dschuyler wrote: > > > > On 2015/05/20 01:02:31, groby wrote: > > > > > This still makes me queasy. You are currently not implementing the > > > > > NSTableViewDataSource API as specified. > > > > > > > > > > It's fine to skip setObjectValue for read-only tables, but this > > technically > > > > > _needs_ to be implemented. > > > > > > > > > > Can you put a breakpoint/LOG in here and see if this is ever called? > > > > > > > > It is being called. > > > > > > > > Here's a link to a prior version of this function that returned a value > and > > > the > > > > discussion about it: > > > > > > > > > > https://codereview.chromium.org/1099403005/diff/200001/chrome/browser/ui/coco... > > > > > > > > Should I change it back to returning a value? > > > > > > No, we should try to understand what's actually going on first :) > (Seriously. > > > While Cocoa is mysterious, please make sure you understand why things are > > > there/need to be done. It'll make it much less fragile) > > > > > > Implementing the data source is technically enough to display a cell-based > > > NSTableView, as per docs. (Everything on NSTableViewDelegate is optional > > > customization) > > > > > > So, where is the value from the datasource communicated to the cell? The > docs > > > are unfortunately not very clear on the subject, but the fact that this is > > > objectValueForTableColumn means likely that this is an objectValue for an > > > NSCell. > > > > > > But don't trust me, verify for yourself. print out callstacks from here and > > from > > > your cell's setObjectValue: > > > > > > Better, turn on prints of all messages as sent around this, via > > > instrumentObjcMessageSends. (See this article on debugging message flow: > > > http://www.dribin.org/dave/blog/archives/2006/04/22/tracing_objc/ > > > And read the technote on debugging, which will change your life: > > > https://developer.apple.com/library/mac/technotes/tn2124/_index.html) > > > > > > You'll see that as the NSTableView displays individual cells, it will call > > this > > > function to get an objectValue, and then set it on the appropriate cell. > > > > > > > > > > > > > I'll look into this further. I'm going to put an interim patch in without > this. > > Waiting for the final patch before I do a full review, then. Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:20, dschuyler wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > Please don't perpetuate ii :) Best, don't even loop manually. > > > > > > AutocompleteResult conforms to STL's iterator conventions, so > > > for (const AutocompleteMatch& match : result) { > > > > > > will do the trick. Plus, potentially a removeObjectAtIndex:0 at the end if > we > > > hide the top match. Yes, we pay one extra conversion, but it makes the code > > more > > > readable. > > > > The <should hide top match> stuff is a discontinued experiment afaik. Peter > had > > asked if I wanted to remove it, but I was planning to minimize this CL and do > it > > later. It can be done now if it makes this CL simpler. > > > > Done. > > If you can do that as a prior CL and rebase this CL onto that cleanup, much > appreciated. That CL is now started. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: NSImage* image = popupView.ImageForMatch(match); On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:21, dschuyler wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > Bleh. I hate we have to pass the popupView. I wonder if we need to hoist the > > > datasource out. > > > > Which direction is the right way to go for this particular CL? > > Could we alter that in a later CL? > > Yes, I think that's fine. It's not perfect, but it's OK (IMHO). Please do add a > TODO/follow-up bug, though. Bug entered 492896 https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:21, dschuyler wrote: > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > On 2015/05/21 03:01:48, groby wrote: > > > > chain methods :) > > > > > > For tests, I'm more lenient about -autorelease, as the -setDataCell: call > > above. > > > Little bit more towards the easy-to-read side of the balance versus the > > > basically-free-performance side. > > > > I'd like to keep the reference counting correct. > > Is it better to have the scoped object or the autorelease? > > It's a minimal cost, so I'm not too worried. I lean slightly towards the chained > methods (because Cocoa), but if you prefer scoped_nsobject, there's enough code > that does the same. Dealer's choice :) I also vote for the easy-to-read, but it sounds like my easy-to-read perspective is different. Being more of a CPP programmer than OBJC, it's easier to standardize on using ~either~ autorelease or scoped_nsobject. It's harder to read (and write) ~sometimes~ use autorelease and sometimes use scoped_object. Acknowledged. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm:278: const AutocompleteMatch& match) const { On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:21, dschuyler wrote: > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > I was wondering earlier if this could just be pulled down to the client > code, > > > but from here it looks like -initWithMatchResults:popupView: either needs > > |this| > > > to bridge, or a direct ref to |model_|, or some sort of new > > > image-finder-for-match interface. Not sure the latter is worth the while. > > > > I wondered about the same. In the scope of 'this is a CL to convert from > > NSMatrix to NSTableView' should the image for match change? > > I think we've heaped on enough change :) Follow-up bug, please? The bug is 492896 Done.
minor style-type responses which really probably don't matter to the CL. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/26 18:40:20, dschuyler wrote: > On 2015/05/21 20:40:27, Scott Hess wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > Why not keep it directly in array_? > > > > array_ is NSArray. Which makes me wonder if array_.reset([array copy]). I > > can't think of any strong reason against array_ being NSMutableArray. It's > less > > correct in a dimension which is fairly irrelevant. Then again this is kind of > a > > rathole to go down. > > If there are good reasons to choose style A or B without a clear winner, I'm > inclined to stay with whichever way is currently written. Of course, it's up to > you two :) [to paraphrase a friend of mine]: Is one way more betterer than the > other? This is like const functions in C++, where there's right, and there's sanity. NSArray should be immutable, so technically array_.reset([array copy]) is more correcter. But so long as you pass off the only copy and never downcast to modify things, it doesn't really matter if the actual array_ value is an NSArray or NSMutableArray, and just using the array you're constructing things in is cheaper. IMHO since this is a transient UI element, storing the construction array is just fine, there's not a lot of scope for things to go awry. If it was calculating this once and then storing it for long-term use, I'd flip to wanting an immutable copy. Style-wise, another place I get uncomfortable is if someone has an internal mutable array and returns an NSArray to some caller, since that can allow for subtle bugs if the caller expects that to be an immutable copy, which isn't going to come up in this case. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/28 20:34:22, dschuyler wrote: > On 2015/05/26 21:23:22, groby wrote: > > On 2015/05/26 18:40:21, dschuyler wrote: > > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > > On 2015/05/21 03:01:48, groby wrote: > > > > > chain methods :) > > > > > > > > For tests, I'm more lenient about -autorelease, as the -setDataCell: call > > > above. > > > > Little bit more towards the easy-to-read side of the balance versus the > > > > basically-free-performance side. > > > > > > I'd like to keep the reference counting correct. > > > Is it better to have the scoped object or the autorelease? > > > > It's a minimal cost, so I'm not too worried. I lean slightly towards the > chained > > methods (because Cocoa), but if you prefer scoped_nsobject, there's enough > code > > that does the same. Dealer's choice :) > > I also vote for the easy-to-read, but it sounds like my easy-to-read perspective > is different. Being more of a CPP programmer than OBJC, it's easier to > standardize on using ~either~ autorelease or scoped_nsobject. It's harder to > read (and write) ~sometimes~ use autorelease and sometimes use scoped_object. > > Acknowledged. I actually gave up on CPP vs OBJC long ago, and mostly just restrict myself to "Be as consistent as possible for the scope". It's the switching back and forth between styles which generates bugs. That said, IMHO test code in Objective-C is very likely to have autoreleased objects, such as from +[NSArray arrayWithObjects:], so it's harder to take a firm line.
A few quick drive-by questions. https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:363: - (id)copyWithZone:(NSZone*)zone { Why does the cellData need copyWithZone? https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:410: - (void)drawMatchWithFrame:(NSRect)cellFrame Draw routines really belong on the cell, not the data. https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: Kill a blank line, save a byte! ;) https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:33: [cell_ setRepresentedObject:cellData_]; I thought you switched to objectValue?
https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:37: base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]); On 2015/05/29 18:00:26, Scott Hess wrote: > On 2015/05/26 18:40:20, dschuyler wrote: > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > On 2015/05/21 03:01:48, groby wrote: > > > > Why not keep it directly in array_? > > > > > > array_ is NSArray. Which makes me wonder if array_.reset([array copy]). I > > > can't think of any strong reason against array_ being NSMutableArray. It's > > less > > > correct in a dimension which is fairly irrelevant. Then again this is kind > of > > a > > > rathole to go down. > > > > If there are good reasons to choose style A or B without a clear winner, I'm > > inclined to stay with whichever way is currently written. Of course, it's up > to > > you two :) [to paraphrase a friend of mine]: Is one way more betterer than > the > > other? > > This is like const functions in C++, where there's right, and there's sanity. > NSArray should be immutable, so technically array_.reset([array copy]) is more > correcter. But so long as you pass off the only copy and never downcast to > modify things, it doesn't really matter if the actual array_ value is an NSArray > or NSMutableArray, and just using the array you're constructing things in is > cheaper. > > IMHO since this is a transient UI element, storing the construction array is > just fine, there's not a lot of scope for things to go awry. If it was > calculating this once and then storing it for long-term use, I'd flip to wanting > an immutable copy. Style-wise, another place I get uncomfortable is if someone > has an internal mutable array and returns an NSArray to some caller, since that > can allow for subtle bugs if the caller expects that to be an immutable copy, > which isn't going to come up in this case. Thanks Done. https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:47: [[OmniboxPopupCellData alloc] init]); On 2015/05/29 18:00:26, Scott Hess wrote: > On 2015/05/28 20:34:22, dschuyler wrote: > > On 2015/05/26 21:23:22, groby wrote: > > > On 2015/05/26 18:40:21, dschuyler wrote: > > > > On 2015/05/21 20:40:27, Scott Hess wrote: > > > > > On 2015/05/21 03:01:48, groby wrote: > > > > > > chain methods :) > > > > > > > > > > For tests, I'm more lenient about -autorelease, as the -setDataCell: > call > > > > above. > > > > > Little bit more towards the easy-to-read side of the balance versus the > > > > > basically-free-performance side. > > > > > > > > I'd like to keep the reference counting correct. > > > > Is it better to have the scoped object or the autorelease? > > > > > > It's a minimal cost, so I'm not too worried. I lean slightly towards the > > chained > > > methods (because Cocoa), but if you prefer scoped_nsobject, there's enough > > code > > > that does the same. Dealer's choice :) > > > > I also vote for the easy-to-read, but it sounds like my easy-to-read > perspective > > is different. Being more of a CPP programmer than OBJC, it's easier to > > standardize on using ~either~ autorelease or scoped_nsobject. It's harder to > > read (and write) ~sometimes~ use autorelease and sometimes use scoped_object. > > > > Acknowledged. > > I actually gave up on CPP vs OBJC long ago, and mostly just restrict myself to > "Be as consistent as possible for the scope". It's the switching back and forth > between styles which generates bugs. > > That said, IMHO test code in Objective-C is very likely to have autoreleased > objects, such as from +[NSArray arrayWithObjects:], so it's harder to take a > firm line. Done. https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:363: - (id)copyWithZone:(NSZone*)zone { On 2015/06/05 01:28:47, groby wrote: > Why does the cellData need copyWithZone? copyWithZone is called by setObjectValue. Maybe I'm doing something wrong with the setObjectValue in tableView:willDisplayCell:forTableColumn:row? That call looks like this: [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]]; https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:410: - (void)drawMatchWithFrame:(NSRect)cellFrame On 2015/06/05 01:28:47, groby wrote: > Draw routines really belong on the cell, not the data. Done. https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: On 2015/06/05 01:28:47, groby wrote: > Kill a blank line, save a byte! ;) Done. https://codereview.chromium.org/1099403005/diff/520001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:33: [cell_ setRepresentedObject:cellData_]; On 2015/06/05 01:28:47, groby wrote: > I thought you switched to objectValue? Thanks! I thought so too. Done.
https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/380001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:40: for (size_t ii = 0; ii < rows; ++ii) { On 2015/05/26 21:23:22, groby wrote: > On 2015/05/26 18:40:20, dschuyler wrote: > > On 2015/05/21 03:01:48, groby wrote: > > > Please don't perpetuate ii :) Best, don't even loop manually. > > > > > > AutocompleteResult conforms to STL's iterator conventions, so > > > for (const AutocompleteMatch& match : result) { > > > > > > will do the trick. Plus, potentially a removeObjectAtIndex:0 at the end if > we > > > hide the top match. Yes, we pay one extra conversion, but it makes the code > > more > > > readable. > > > > The <should hide top match> stuff is a discontinued experiment afaik. Peter > had > > asked if I wanted to remove it, but I was planning to minimize this CL and do > it > > later. It can be done now if it makes this CL simpler. > > > > Done. > > If you can do that as a prior CL and rebase this CL onto that cleanup, much > appreciated. Done.
Almost, with a few more fixes. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:14: @class OmniboxPopupCell; I don't think you need that any more https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:19: base::scoped_nsobject<NSAttributedString> contents_; If you use these purely as data container and nothing else, you might as well use a pure NSAttributedString and then have a @property(retain, noatomix) and synthesize the getters/setters. Much cleaner. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:371: OmniboxPopupCellData* copy = [[OmniboxPopupCellData alloc] init]; Since we seem to retain all the members - iow, this is an immutable structure. So why not return [self retain] ? https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: - (NSAttributedString*)description; That's already defined in an anonymous category in the main file, so probably should be a public method. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:17: - (void)setImage:(NSImage*)image; Instead of having setters on what's otherwise an immutable object, I'd suggest - (instanceType)initWithDescription:(NSAttributedString*)string image:(NSImage*)image And just build and set the celldata as you need it. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:49: [cellData_ setImage:[NSImage imageNamed:NSImageNameInfo]]; This doesn't what you expect it to do - you already did a setObjectValue: on cellData, which created a copy. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: if (match.answer && answerImage) Again, this modifies something that's technically immutable - I'd rather you always pass answerImage into the initWithMatch and make this call there. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:55: [cellData setMaxMatchContentsWidth:max_match_contents_width]; Grumblemumble immutable grumblemumble. (We can get away with it because we know it won't be used by anybody else before this, but... yuck) Since the MaxMatchContentsWidth is the same for all cells, can we move that elsewhere? https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); Usually, if you init with a mutable array, you copy/retain (because you don't want it mutated behind your back) https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:76: return nil; As discussed in earlier CLs: This should return the actual objectValue that is given to the cell before being displayed. I.e. the CellData associated with this rowIndex. That's the _job_ of this API. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:83: } NOTREACHED, please, since we'll never modify values. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:91: [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]]; [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]]; is handled if tableView:objectValueForTableColumn: returns the proper value. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:103: - (void)highlightRowAt:(NSInteger)rowIndex { - (void)setHighlightedRow:(NSInteger)rowIndex setters are always marked with a beginning "set" https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:126: [[NSTableColumn alloc] initWithIdentifier:@"MainCell"]); Well, it'd be the "MainColumn" if that's the ID we want to use.
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:371: OmniboxPopupCellData* copy = [[OmniboxPopupCellData alloc] init]; On 2015/06/11 01:22:17, groby wrote: > Since we seem to retain all the members - iow, this is an immutable structure. > > So why not return [self retain] ? Yeah, as long as it's returning a shallow copy, should work fine. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: - (NSAttributedString*)description; On 2015/06/11 01:22:17, groby wrote: > That's already defined in an anonymous category in the main file, so probably > should be a public method. Any concerns about this overriding NSObject protocol's -description method? I don't think it would cause problems, I just initially read this differently than I think you wrote it, and that made me wonder :-). https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:17: - (void)setImage:(NSImage*)image; On 2015/06/11 01:22:17, groby wrote: > Instead of having setters on what's otherwise an immutable object, I'd suggest > > - (instanceType)initWithDescription:(NSAttributedString*)string > image:(NSImage*)image > > And just build and set the celldata as you need it. I agree, for a data object you should either aim for fully-mutable or fully-immutable, and in this case it really doesn't need to be mutable except for a setup-time wart. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/11 01:22:17, groby wrote: > Usually, if you init with a mutable array, you copy/retain (because you don't > want it mutated behind your back) I think -copy returns a reference, so you just do: array_.reset([array copy]); BUT, |array| should be mutable in the first place, so really the caller should be passing an NSArray, and will either need to put it in a scoper or use -autorelease (usually a method would be expected to add a reference, not keep the reference).
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:14: @class OmniboxPopupCell; On 2015/06/11 01:22:17, groby wrote: > I don't think you need that any more Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:19: base::scoped_nsobject<NSAttributedString> contents_; On 2015/06/11 01:22:17, groby wrote: > If you use these purely as data container and nothing else, you might as well > use a pure NSAttributedString and then have a @property(retain, noatomix) and > synthesize the getters/setters. Much cleaner. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:371: OmniboxPopupCellData* copy = [[OmniboxPopupCellData alloc] init]; On 2015/06/11 01:22:17, groby wrote: > Since we seem to retain all the members - iow, this is an immutable structure. > > So why not return [self retain] ? That seems to work nicely. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:371: OmniboxPopupCellData* copy = [[OmniboxPopupCellData alloc] init]; On 2015/06/11 21:52:02, Scott Hess wrote: > On 2015/06/11 01:22:17, groby wrote: > > Since we seem to retain all the members - iow, this is an immutable structure. > > > > So why not return [self retain] ? > > Yeah, as long as it's returning a shallow copy, should work fine. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: - (NSAttributedString*)description; On 2015/06/11 01:22:17, groby wrote: > That's already defined in an anonymous category in the main file, so probably > should be a public method. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:16: - (NSAttributedString*)description; On 2015/06/11 21:52:02, Scott Hess wrote: > On 2015/06/11 01:22:17, groby wrote: > > That's already defined in an anonymous category in the main file, so probably > > should be a public method. > > Any concerns about this overriding NSObject protocol's -description method? I > don't think it would cause problems, I just initially read this differently than > I think you wrote it, and that made me wonder :-). While I'm ok with it being description, I can also change it - if you'd like it changed, a suggestion on what to change it to would be great :) https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:17: - (void)setImage:(NSImage*)image; On 2015/06/11 01:22:17, groby wrote: > Instead of having setters on what's otherwise an immutable object, I'd suggest > > - (instanceType)initWithDescription:(NSAttributedString*)string > image:(NSImage*)image > > And just build and set the celldata as you need it. I used the existing initWithMatch, with the hope that's ok. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:17: - (void)setImage:(NSImage*)image; On 2015/06/11 21:52:02, Scott Hess wrote: > On 2015/06/11 01:22:17, groby wrote: > > Instead of having setters on what's otherwise an immutable object, I'd suggest > > > > > - (instanceType)initWithDescription:(NSAttributedString*)string > > image:(NSImage*)image > > > > And just build and set the celldata as you need it. > > I agree, for a data object you should either aim for fully-mutable or > fully-immutable, and in this case it really doesn't need to be mutable except > for a setup-time wart. I think we're going in the fully-immutable direction (though there is still a test function that cheats and another that deals with the prefix that I'm trying not to change too much in this CL). https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:49: [cellData_ setImage:[NSImage imageNamed:NSImageNameInfo]]; On 2015/06/11 01:22:17, groby wrote: > This doesn't what you expect it to do - you already did a setObjectValue: on > cellData, which created a copy. > Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:42: if (match.answer && answerImage) On 2015/06/11 01:22:18, groby wrote: > Again, this modifies something that's technically immutable - I'd rather you > always pass answerImage into the initWithMatch and make this call there. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:55: [cellData setMaxMatchContentsWidth:max_match_contents_width]; On 2015/06/11 01:22:18, groby wrote: > Grumblemumble immutable grumblemumble. > > (We can get away with it because we know it won't be used by anybody else before > this, but... yuck) > > Since the MaxMatchContentsWidth is the same for all cells, can we move that > elsewhere? Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/11 01:22:17, groby wrote: > Usually, if you init with a mutable array, you copy/retain (because you don't > want it mutated behind your back) Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/11 21:52:02, Scott Hess wrote: > On 2015/06/11 01:22:17, groby wrote: > > Usually, if you init with a mutable array, you copy/retain (because you don't > > want it mutated behind your back) > > I think -copy returns a reference, so you just do: > array_.reset([array copy]); > BUT, |array| should be mutable in the first place, so really the caller should > be passing an NSArray, and will either need to put it in a scoper or use > -autorelease (usually a method would be expected to add a reference, not keep > the reference). I'm having trouble following this, is this a mistype: "should be [im]mutable in the first place" or similar? https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:76: return nil; On 2015/06/11 01:22:18, groby wrote: > As discussed in earlier CLs: This should return the actual objectValue that is > given to the cell before being displayed. I.e. the CellData associated with this > rowIndex. > > That's the _job_ of this API. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:83: } On 2015/06/11 01:22:17, groby wrote: > NOTREACHED, please, since we'll never modify values. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:91: [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]]; On 2015/06/11 01:22:17, groby wrote: > [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]]; > is handled if tableView:objectValueForTableColumn: returns the proper value. Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:103: - (void)highlightRowAt:(NSInteger)rowIndex { On 2015/06/11 01:22:18, groby wrote: > - (void)setHighlightedRow:(NSInteger)rowIndex > > setters are always marked with a beginning "set" Done. https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:126: [[NSTableColumn alloc] initWithIdentifier:@"MainCell"]); On 2015/06/11 01:22:17, groby wrote: > Well, it'd be the "MainColumn" if that's the ID we want to use. Done.
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/11 22:34:22, dschuyler wrote: > On 2015/06/11 21:52:02, Scott Hess wrote: > > On 2015/06/11 01:22:17, groby wrote: > > > Usually, if you init with a mutable array, you copy/retain (because you > don't > > > want it mutated behind your back) > > > > I think -copy returns a reference, so you just do: > > array_.reset([array copy]); > > BUT, |array| should be mutable in the first place, so really the caller should > > be passing an NSArray, and will either need to put it in a scoper or use > > -autorelease (usually a method would be expected to add a reference, not keep > > the reference). > > I'm having trouble following this, is this a mistype: "should be [im]mutable in > the first place" or similar? Yeah, I think there was a missing n't or im in there. If you don't need something mutable, don't ask for something mutable, I think.
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/11 22:36:19, Scott Hess wrote: > On 2015/06/11 22:34:22, dschuyler wrote: > > On 2015/06/11 21:52:02, Scott Hess wrote: > > > On 2015/06/11 01:22:17, groby wrote: > > > > Usually, if you init with a mutable array, you copy/retain (because you > > don't > > > > want it mutated behind your back) > > > > > > I think -copy returns a reference, so you just do: > > > array_.reset([array copy]); > > > BUT, |array| should be mutable in the first place, so really the caller > should > > > be passing an NSArray, and will either need to put it in a scoper or use > > > -autorelease (usually a method would be expected to add a reference, not > keep > > > the reference). > > > > I'm having trouble following this, is this a mistype: "should be [im]mutable > in > > the first place" or similar? > > Yeah, I think there was a missing n't or im in there. If you don't need > something mutable, don't ask for something mutable, I think. I think we still want the data member to be a mutable array (from prior review comments in this CL). Is it correct to make the arg non mutable and copy the array? Done.
https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:38: @property(retain, nonatomic) NSAttributedString* contents; We ultimately want this readonly, since this _should_ be immutable. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:43: @property(nonatomic) CGFloat contentsOffset; See above re: immutable. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { Skip the empty braces - not needed if you don't have data. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:65: withCellData:(OmniboxPopupCellData*)cellData Does this need cellData? Can't it retrieve that from -objectValue? https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:299: @synthesize contents = contents_; This is the "default" mode for @synthesize. Since XCode 4.4/clang 4, the compiler will autosynthesize for you - so all these lines can go! Yay! https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:344: // const base::char16 space(' '); Kill comment https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: description_ = [answerString.release() retain]; scoped_nsobject's release is not ObjC's release - it just means scoped_nsobject doesn't track any more. (See [1]) Since it was started with a refCount of 1, this would now create an object with a refCount of 2, and we'd leak. You want autorelease() instead. (Technically, you could just assign to |description_|, but that muddies readability for refcounts) [1] https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/scoped_ns... https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:360: description_ = nil; Not necessary - all ivars are initialized to nil in ObjC. See https://developer.apple.com/library/mac/documentation/General/Conceptual/Coco... https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:421: if ([cellData image]) { This check is not necessary. (A nil image would just compute an imageRect, and then send the draw message to nil - which does nothing. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:454: if ([cellData answerImage]) { Unnecessary check https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:472: - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame Didn't see a prototype for this? https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:481: base::mac::ObjCCastStrict<OmniboxPopupMatrix>(controlView); You could just pass in the OmniboxPopupMatrix directly - it seems this is only called from places where we've done the cast already. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:528: std::floor((NSHeight(cellFrame) - NSHeight(textRect)) / 2.0); Since this is only part of the match, are you sure we want to flip the rect in the entire cellFrame? Or do we just want to draw the string RTL, but preserve overall position? https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @interface OmniboxPopupCellData () If we _must_ mutate, I'd prefer you define the setter here, explicitly violating the contract we set up in the header. But ideally, I'd suggest an -initWithContents method. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:56: [cellData_ setContents:text]; You don't have cellData_ set yet. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: - (instancetype)init { Do we need this init? If so, it should be named in an interface. Also, there should only be one designated initializer, and all others should use it.[1] https://developer.apple.com/library/ios/documentation/General/Conceptual/DevP... https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:58: - (instancetype)initWithArray:(NSArray*)array { Again, not specified in an interface. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:118: @synthesize separator = separator_; Can skip synthesize
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/12 00:43:26, dschuyler wrote: > On 2015/06/11 22:36:19, Scott Hess wrote: > > On 2015/06/11 22:34:22, dschuyler wrote: > > > On 2015/06/11 21:52:02, Scott Hess wrote: > > > > On 2015/06/11 01:22:17, groby wrote: > > > > > Usually, if you init with a mutable array, you copy/retain (because you > > > don't > > > > > want it mutated behind your back) > > > > > > > > I think -copy returns a reference, so you just do: > > > > array_.reset([array copy]); > > > > BUT, |array| should be mutable in the first place, so really the caller > > should > > > > be passing an NSArray, and will either need to put it in a scoper or use > > > > -autorelease (usually a method would be expected to add a reference, not > > keep > > > > the reference). > > > > > > I'm having trouble following this, is this a mistype: "should be [im]mutable > > in > > > the first place" or similar? > > > > Yeah, I think there was a missing n't or im in there. If you don't need > > something mutable, don't ask for something mutable, I think. > > I think we still want the data member to be a mutable array (from prior review > comments in this CL). Is it correct to make the arg non mutable and copy the > array? > > Done. I think maybe you're wavering back and forth based on implementation details, not abstraction boundaries. AFAICT, after initialization, this class never needs to change the contents of array_, so array_ should be an immutable NSArray instance. -initWithMatchResults:* is using array_ as an NSMutableArray for construction purposes only, so it should be using a local scoped_nsobject<NSMutableArray> for that, which then either has its only reference put in array_ (so it is never mutated again), or a -copy put into array_ (which guarantees that it can't be mutated again). Either way the implementation details of initialization should not be leaking into the class' overall contract. The prior comment (at least the one I'm thinking of) wasn't about whether the data member should be a mutable array, it was about whether it's worthwhile to make an immutable copy, versus simply using the mutable array you already have. NSMutableArray is an NSArray subclass, so you can do it either way. But -copy has a non-zero cost, and if nobody ever changes the NSMutableArray (because you only have an NSArray reference to it), then the -copy cost doesn't gain any advantages. The common case where this kind of thing goes awry is where you have an NSMutableArray as part of your implementation, and implement something like -(NSArray*)array { return mutable_array_; }. If the caller then decides to iterate over that array calling into your API to remove selected items, then the array being iterated unexpectedly changes contents while being iterated, which is obviously going to be buggy. That's why I wrote the "only reference" bit above, because that is only possible if your code keeps both mutable and immutable references to the same object. [I think groby is leaning towards calling -copy and making it immutable, and the cost of that is low enough that I'm merely neutral, so I guess that leans towards make the copy.] https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: description_ = [answerString.release() retain]; On 2015/06/12 18:51:06, groby wrote: > scoped_nsobject's release is not ObjC's release - it just means scoped_nsobject > doesn't track any more. (See [1]) Since it was started with a refCount of 1, > this would now create an object with a refCount of 2, and we'd leak. You want > autorelease() instead. > > (Technically, you could just assign to |description_|, but that muddies > readability for refcounts) > > [1] > https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/scoped_ns... IMHO this would be pretty clear to a C++ programmer: description_.swap(answerString);
https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: description_ = [answerString.release() retain]; On 2015/06/12 20:21:32, Scott Hess wrote: > On 2015/06/12 18:51:06, groby wrote: > > scoped_nsobject's release is not ObjC's release - it just means > scoped_nsobject > > doesn't track any more. (See [1]) Since it was started with a refCount of 1, > > this would now create an object with a refCount of 2, and we'd leak. You want > > autorelease() instead. > > > > (Technically, you could just assign to |description_|, but that muddies > > readability for refcounts) > > > > [1] > > > https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/scoped_ns... > > IMHO this would be pretty clear to a C++ programmer: > description_.swap(answerString); swap won't work, since description_ isn't scoped_nsobject. It's a retained property, which saves a boatload of boilerplate getters/setters.
https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:38: @property(retain, nonatomic) NSAttributedString* contents; On 2015/06/12 18:51:06, groby wrote: > We ultimately want this readonly, since this _should_ be immutable. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:43: @property(nonatomic) CGFloat contentsOffset; On 2015/06/12 18:51:06, groby wrote: > See above re: immutable. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/06/12 18:51:06, groby wrote: > Skip the empty braces - not needed if you don't have data. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: @interface OmniboxPopupCell : NSCell { On 2015/06/12 18:51:06, groby wrote: > Skip the empty braces - not needed if you don't have data. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:65: withCellData:(OmniboxPopupCellData*)cellData On 2015/06/12 18:51:06, groby wrote: > Does this need cellData? Can't it retrieve that from -objectValue? It can retrieve it from objectValue. Which is preferred? https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:65: withCellData:(OmniboxPopupCellData*)cellData On 2015/06/12 18:51:06, groby wrote: > Does this need cellData? Can't it retrieve that from -objectValue? Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:299: @synthesize contents = contents_; On 2015/06/12 18:51:07, groby wrote: > This is the "default" mode for @synthesize. Since XCode 4.4/clang 4, the > compiler will autosynthesize for you - so all these lines can go! Yay! It seems that there is a warning that requires it. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:344: // const base::char16 space(' '); On 2015/06/12 18:51:07, groby wrote: > Kill comment Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:358: description_ = [answerString.release() retain]; On 2015/06/12 18:51:06, groby wrote: > scoped_nsobject's release is not ObjC's release - it just means scoped_nsobject > doesn't track any more. (See [1]) Since it was started with a refCount of 1, > this would now create an object with a refCount of 2, and we'd leak. You want > autorelease() instead. > > (Technically, you could just assign to |description_|, but that muddies > readability for refcounts) > > [1] > https://code.google.com/p/chromium/codesearch#chromium/src/base/mac/scoped_ns... Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:360: description_ = nil; On 2015/06/12 18:51:07, groby wrote: > Not necessary - all ivars are initialized to nil in ObjC. See > https://developer.apple.com/library/mac/documentation/General/Conceptual/Coco... Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:421: if ([cellData image]) { On 2015/06/12 18:51:07, groby wrote: > This check is not necessary. (A nil image would just compute an imageRect, and > then send the draw message to nil - which does nothing. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:454: if ([cellData answerImage]) { On 2015/06/12 18:51:07, groby wrote: > Unnecessary check Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:472: - (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame On 2015/06/12 18:51:06, groby wrote: > Didn't see a prototype for this? Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:481: base::mac::ObjCCastStrict<OmniboxPopupMatrix>(controlView); On 2015/06/12 18:51:06, groby wrote: > You could just pass in the OmniboxPopupMatrix directly - it seems this is only > called from places where we've done the cast already. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:528: std::floor((NSHeight(cellFrame) - NSHeight(textRect)) / 2.0); On 2015/06/12 18:51:06, groby wrote: > Since this is only part of the match, are you sure we want to flip the rect in > the entire cellFrame? Or do we just want to draw the string RTL, but preserve > overall position? I'm not 100% sure. I do have a bug to look into the RTL further: 469362. I'm adding a link to this comment to that bug. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:14: @interface OmniboxPopupCellData () On 2015/06/12 18:51:07, groby wrote: > If we _must_ mutate, I'd prefer you define the setter here, explicitly violating > the contract we set up in the header. > > But ideally, I'd suggest an -initWithContents method. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell_unittest.mm:56: [cellData_ setContents:text]; On 2015/06/12 18:51:07, groby wrote: > You don't have cellData_ set yet. Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:22: - (instancetype)init { On 2015/06/12 18:51:07, groby wrote: > Do we need this init? > > If so, it should be named in an interface. Also, there should only be one > designated initializer, and all others should use it.[1] > > > https://developer.apple.com/library/ios/documentation/General/Conceptual/DevP... Done. https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:58: - (instancetype)initWithArray:(NSArray*)array { On 2015/06/12 18:51:07, groby wrote: > Again, not specified in an interface. It's a test-only function. It's in the interface in omnibox_popup_matrix_unittest.mm. Is that the right thing to do or should I also specify it here? https://codereview.chromium.org/1099403005/diff/640001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:118: @synthesize separator = separator_; On 2015/06/12 18:51:07, groby wrote: > Can skip synthesize :(
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/12 20:21:32, Scott Hess wrote: > On 2015/06/12 00:43:26, dschuyler wrote: > > On 2015/06/11 22:36:19, Scott Hess wrote: > > > On 2015/06/11 22:34:22, dschuyler wrote: > > > > On 2015/06/11 21:52:02, Scott Hess wrote: > > > > > On 2015/06/11 01:22:17, groby wrote: > > > > > > Usually, if you init with a mutable array, you copy/retain (because > you > > > > don't > > > > > > want it mutated behind your back) > > > > > > > > > > I think -copy returns a reference, so you just do: > > > > > array_.reset([array copy]); > > > > > BUT, |array| should be mutable in the first place, so really the caller > > > should > > > > > be passing an NSArray, and will either need to put it in a scoper or use > > > > > -autorelease (usually a method would be expected to add a reference, not > > > keep > > > > > the reference). > > > > > > > > I'm having trouble following this, is this a mistype: "should be > [im]mutable > > > in > > > > the first place" or similar? > > > > > > Yeah, I think there was a missing n't or im in there. If you don't need > > > something mutable, don't ask for something mutable, I think. > > > > I think we still want the data member to be a mutable array (from prior review > > comments in this CL). Is it correct to make the arg non mutable and copy the > > array? > > > > Done. > > I think maybe you're wavering back and forth based on implementation details, > not abstraction boundaries. > > AFAICT, after initialization, this class never needs to change the contents of > array_, so array_ should be an immutable NSArray instance. > > -initWithMatchResults:* is using array_ as an NSMutableArray for construction > purposes only, so it should be using a local scoped_nsobject<NSMutableArray> for > that, which then either has its only reference put in array_ (so it is never > mutated again), or a -copy put into array_ (which guarantees that it can't be > mutated again). Either way the implementation details of initialization should > not be leaking into the class' overall contract. > > The prior comment (at least the one I'm thinking of) wasn't about whether the > data member should be a mutable array, it was about whether it's worthwhile to > make an immutable copy, versus simply using the mutable array you already have. > NSMutableArray is an NSArray subclass, so you can do it either way. But -copy > has a non-zero cost, and if nobody ever changes the NSMutableArray (because you > only have an NSArray reference to it), then the -copy cost doesn't gain any > advantages. > > The common case where this kind of thing goes awry is where you have an > NSMutableArray as part of your implementation, and implement something like > -(NSArray*)array { return mutable_array_; }. If the caller then decides to > iterate over that array calling into your API to remove selected items, then the > array being iterated unexpectedly changes contents while being iterated, which > is obviously going to be buggy. That's why I wrote the "only reference" bit > above, because that is only possible if your code keeps both mutable and > immutable references to the same object. > > [I think groby is leaning towards calling -copy and making it immutable, and the > cost of that is low enough that I'm merely neutral, so I guess that leans > towards make the copy.] Thanks. I'm hoping I'm closer now. The array is only mutable during construction. It's still doing the copy, but the array is short. I can see where this is a trade off between a robust api and performance. If I'm following along correctly, we are currently on the robust api side (immutable array and copying). Done.
I'm losing the will to live, here. I'll try to be more pedantic if I ever see follow-on CLs. LGTM, with some nits, some of them "Dealer chooses" sorts of nits. In case of direct conflict prefer groby's feedback. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:17: // NSAttributedString instances for various match components. The comment telling us that the NSAttributedString instances are NSAttributedString instances is redundant. You're moving it, you get to own it :-). Or delete it. That said, I suspect that documenting what the two images mean might make sense. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: // uses information from OmniboxPopupCellData to draw suggestion results. I'd also remove the talking-about-myself-by-given-name here, too. Since this comment documents OmniboxPopupCell, it doesn't need to refer to OmniboxPopupCell. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:404: OmniboxPopupCellData* cellData = [self objectValue]; ObjCCastStrict for this, too (unless it can be nil?). https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:460: offset += NSWidth(imageRect); Something is definitely wrong here, probably indentation. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:472: OmniboxPopupCellData* cellData = [self objectValue]; ObjCCastStrict https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: row:(NSInteger)rowIndex { I think if they fit, these should align the colon, and only do the four-space like this if it doesn't fit. If you consult the style guide and it seems ambiguous, ignore me. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; I really really wish that the documentation was more clear about whether -setDataCell: takes ownership, or adds a reference. This is only correct if it takes ownership. You might want to test by having a temporary, and logging the results of -retainCount before and after the -setDataCell: call. That's not 100% certain, since there could be autorelease pools and the like involved, but if the retain count does not change, that probably means that it takes ownership rather than adding a ref. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end I'm losing the ability to follow the discussion, but personally I would be comfortable with this being in a TestingAPI category exposed in the header file, rather than having multiple copy/paste declarations. The .mm implementation will enforce what it sees at compile-time, but this one could be arbitrarily different and still link and run.
https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/600001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:64: array_.reset([array retain]); On 2015/06/12 21:44:30, dschuyler wrote: > On 2015/06/12 20:21:32, Scott Hess wrote: > > On 2015/06/12 00:43:26, dschuyler wrote: > > > On 2015/06/11 22:36:19, Scott Hess wrote: > > > > On 2015/06/11 22:34:22, dschuyler wrote: > > > > > On 2015/06/11 21:52:02, Scott Hess wrote: > > > > > > On 2015/06/11 01:22:17, groby wrote: > > > > > > > Usually, if you init with a mutable array, you copy/retain (because > > you > > > > > don't > > > > > > > want it mutated behind your back) > > > > > > > > > > > > I think -copy returns a reference, so you just do: > > > > > > array_.reset([array copy]); > > > > > > BUT, |array| should be mutable in the first place, so really the > caller > > > > should > > > > > > be passing an NSArray, and will either need to put it in a scoper or > use > > > > > > -autorelease (usually a method would be expected to add a reference, > not > > > > keep > > > > > > the reference). > > > > > > > > > > I'm having trouble following this, is this a mistype: "should be > > [im]mutable > > > > in > > > > > the first place" or similar? > > > > > > > > Yeah, I think there was a missing n't or im in there. If you don't need > > > > something mutable, don't ask for something mutable, I think. > > > > > > I think we still want the data member to be a mutable array (from prior > review > > > comments in this CL). Is it correct to make the arg non mutable and copy > the > > > array? > > > > > > Done. > > > > I think maybe you're wavering back and forth based on implementation details, > > not abstraction boundaries. > > > > AFAICT, after initialization, this class never needs to change the contents of > > array_, so array_ should be an immutable NSArray instance. > > > > -initWithMatchResults:* is using array_ as an NSMutableArray for construction > > purposes only, so it should be using a local scoped_nsobject<NSMutableArray> > for > > that, which then either has its only reference put in array_ (so it is never > > mutated again), or a -copy put into array_ (which guarantees that it can't be > > mutated again). Either way the implementation details of initialization > should > > not be leaking into the class' overall contract. > > > > The prior comment (at least the one I'm thinking of) wasn't about whether the > > data member should be a mutable array, it was about whether it's worthwhile to > > make an immutable copy, versus simply using the mutable array you already > have. > > NSMutableArray is an NSArray subclass, so you can do it either way. But -copy > > has a non-zero cost, and if nobody ever changes the NSMutableArray (because > you > > only have an NSArray reference to it), then the -copy cost doesn't gain any > > advantages. > > > > The common case where this kind of thing goes awry is where you have an > > NSMutableArray as part of your implementation, and implement something like > > -(NSArray*)array { return mutable_array_; }. If the caller then decides to > > iterate over that array calling into your API to remove selected items, then > the > > array being iterated unexpectedly changes contents while being iterated, which > > is obviously going to be buggy. That's why I wrote the "only reference" bit > > above, because that is only possible if your code keeps both mutable and > > immutable references to the same object. > > > > [I think groby is leaning towards calling -copy and making it immutable, and > the > > cost of that is low enough that I'm merely neutral, so I guess that leans > > towards make the copy.] > > Thanks. I'm hoping I'm closer now. The array is only mutable during > construction. It's still doing the copy, but the array is short. I can see > where this is a trade off between a robust api and performance. If I'm > following along correctly, we are currently on the robust api side (immutable > array and copying). Yes, please. I now my future self, and she'll make horrible mistakes when the API is fragile. And since I like her, let's protect her ;) Along those same lines, let's also only accept an NSArray, not an NSMutableArray. (It'll still accept NSMutableArray, but it won't invite you to use one) in general, my API preference is to use the least specialized type possible, unless there are very specific performance constraints.
LGTM % comments. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 22:21:59, Scott Hess wrote: > I really really wish that the documentation was more clear about whether > -setDataCell: takes ownership, or adds a reference. This is only correct if it > takes ownership. You might want to test by having a temporary, and logging the > results of -retainCount before and after the -setDataCell: call. That's not > 100% certain, since there could be autorelease pools and the like involved, but > if the retain count does not change, that probably means that it takes ownership > rather than adding a ref. The docs say "@property (strong) id dataCell". It seems strong is the new fancy way to say retain, so it takes ownership. You're safe. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end On 2015/06/12 22:21:59, Scott Hess wrote: > I'm losing the ability to follow the discussion, but personally I would be > comfortable with this being in a TestingAPI category exposed in the header file, > rather than having multiple copy/paste declarations. The .mm implementation > will enforce what it sees at compile-time, but this one could be arbitrarily > different and still link and run. What Scott said. Anonymous categories should only be applied if it's _actually_ private to the .mm file the category is in.
https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 22:43:01, groby wrote: > On 2015/06/12 22:21:59, Scott Hess wrote: > > I really really wish that the documentation was more clear about whether > > -setDataCell: takes ownership, or adds a reference. This is only correct if > it > > takes ownership. You might want to test by having a temporary, and logging > the > > results of -retainCount before and after the -setDataCell: call. That's not > > 100% certain, since there could be autorelease pools and the like involved, > but > > if the retain count does not change, that probably means that it takes > ownership > > rather than adding a ref. > > The docs say "@property (strong) id dataCell". It seems strong is the new fancy > way to say retain, so it takes ownership. You're safe. I think that means it takes a reference under non-ARC, which implies that after this statement runs there will be two outstanding references, one of which nobody is tracking.
https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 22:49:20, Scott Hess wrote: > On 2015/06/12 22:43:01, groby wrote: > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > I really really wish that the documentation was more clear about whether > > > -setDataCell: takes ownership, or adds a reference. This is only correct if > > it > > > takes ownership. You might want to test by having a temporary, and logging > > the > > > results of -retainCount before and after the -setDataCell: call. That's not > > > 100% certain, since there could be autorelease pools and the like involved, > > but > > > if the retain count does not change, that probably means that it takes > > ownership > > > rather than adding a ref. > > > > The docs say "@property (strong) id dataCell". It seems strong is the new > fancy > > way to say retain, so it takes ownership. You're safe. > > I think that means it takes a reference under non-ARC, which implies that after > this statement runs there will be two outstanding references, one of which > nobody is tracking. Gah. Of course. Sorry, Friday-afternoon-CL-fatigue.
https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:17: // NSAttributedString instances for various match components. On 2015/06/12 22:21:59, Scott Hess wrote: > The comment telling us that the NSAttributedString instances are > NSAttributedString instances is redundant. You're moving it, you get to own it > :-). Or delete it. > > That said, I suspect that documenting what the two images mean might make sense. Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: // uses information from OmniboxPopupCellData to draw suggestion results. On 2015/06/12 22:21:59, Scott Hess wrote: > I'd also remove the talking-about-myself-by-given-name here, too. Since this > comment documents OmniboxPopupCell, it doesn't need to refer to > OmniboxPopupCell. Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:404: OmniboxPopupCellData* cellData = [self objectValue]; On 2015/06/12 22:21:59, Scott Hess wrote: > ObjCCastStrict for this, too (unless it can be nil?). Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:460: offset += NSWidth(imageRect); On 2015/06/12 22:21:59, Scott Hess wrote: > Something is definitely wrong here, probably indentation. Hmm, cl format didn't want to move it until I put it all on one line - then it formatted it properly. Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:472: OmniboxPopupCellData* cellData = [self objectValue]; On 2015/06/12 22:21:59, Scott Hess wrote: > ObjCCastStrict Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: row:(NSInteger)rowIndex { On 2015/06/12 22:21:59, Scott Hess wrote: > I think if they fit, these should align the colon, and only do the four-space > like this if it doesn't fit. If you consult the style guide and it seems > ambiguous, ignore me. This is formatted the way cl format wants to do it. I realize that is not really the authority of the style guide, but I'm willing to rely on it for this case if that's cool. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 22:49:20, Scott Hess wrote: > On 2015/06/12 22:43:01, groby wrote: > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > I really really wish that the documentation was more clear about whether > > > -setDataCell: takes ownership, or adds a reference. This is only correct if > > it > > > takes ownership. You might want to test by having a temporary, and logging > > the > > > results of -retainCount before and after the -setDataCell: call. That's not > > > 100% certain, since there could be autorelease pools and the like involved, > > but > > > if the retain count does not change, that probably means that it takes > > ownership > > > rather than adding a ref. > > > > The docs say "@property (strong) id dataCell". It seems strong is the new > fancy > > way to say retain, so it takes ownership. You're safe. > > I think that means it takes a reference under non-ARC, which implies that after > this statement runs there will be two outstanding references, one of which > nobody is tracking. Does that mean that this should be an autorelease? https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end On 2015/06/12 22:43:01, groby wrote: > On 2015/06/12 22:21:59, Scott Hess wrote: > > I'm losing the ability to follow the discussion, but personally I would be > > comfortable with this being in a TestingAPI category exposed in the header > file, > > rather than having multiple copy/paste declarations. The .mm implementation > > will enforce what it sees at compile-time, but this one could be arbitrarily > > different and still link and run. > > What Scott said. Anonymous categories should only be applied if it's _actually_ > private to the .mm file the category is in. My intention is that it is private. If my intention is incorrect, then I should move this. Is it wrong for me to intend this to be private?
On 2015/06/12 23:07:54, dschuyler wrote: > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h (right): > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:17: // NSAttributedString > instances for various match components. > On 2015/06/12 22:21:59, Scott Hess wrote: > > The comment telling us that the NSAttributedString instances are > > NSAttributedString instances is redundant. You're moving it, you get to own > it > > :-). Or delete it. > > > > That said, I suspect that documenting what the two images mean might make > sense. > > Done. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h:61: // uses information > from OmniboxPopupCellData to draw suggestion results. > On 2015/06/12 22:21:59, Scott Hess wrote: > > I'd also remove the talking-about-myself-by-given-name here, too. Since this > > comment documents OmniboxPopupCell, it doesn't need to refer to > > OmniboxPopupCell. > > Done. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm (right): > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:404: OmniboxPopupCellData* > cellData = [self objectValue]; > On 2015/06/12 22:21:59, Scott Hess wrote: > > ObjCCastStrict for this, too (unless it can be nil?). > > Done. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:460: offset += > NSWidth(imageRect); > On 2015/06/12 22:21:59, Scott Hess wrote: > > Something is definitely wrong here, probably indentation. > > Hmm, cl format didn't want to move it until I put it all on one line - then it > formatted it properly. > > Done. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm:472: OmniboxPopupCellData* > cellData = [self objectValue]; > On 2015/06/12 22:21:59, Scott Hess wrote: > > ObjCCastStrict > > Done. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: > row:(NSInteger)rowIndex { > On 2015/06/12 22:21:59, Scott Hess wrote: > > I think if they fit, these should align the colon, and only do the four-space > > like this if it doesn't fit. If you consult the style guide and it seems > > ambiguous, ignore me. > > This is formatted the way cl format wants to do it. I realize that is not > really the authority of the style guide, but I'm willing to rely on it for this > case if that's cool. > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column > setDataCell:[[OmniboxPopupCell alloc] init]]; > On 2015/06/12 22:49:20, Scott Hess wrote: > > On 2015/06/12 22:43:01, groby wrote: > > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > > I really really wish that the documentation was more clear about whether > > > > -setDataCell: takes ownership, or adds a reference. This is only correct > if > > > it > > > > takes ownership. You might want to test by having a temporary, and > logging > > > the > > > > results of -retainCount before and after the -setDataCell: call. That's > not > > > > 100% certain, since there could be autorelease pools and the like > involved, > > > but > > > > if the retain count does not change, that probably means that it takes > > > ownership > > > > rather than adding a ref. > > > > > > The docs say "@property (strong) id dataCell". It seems strong is the new > > fancy > > > way to say retain, so it takes ownership. You're safe. > > > > I think that means it takes a reference under non-ARC, which implies that > after > > this statement runs there will be two outstanding references, one of which > > nobody is tracking. > > Does that mean that this should be an autorelease? > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): > > https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... > chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end > On 2015/06/12 22:43:01, groby wrote: > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > I'm losing the ability to follow the discussion, but personally I would be > > > comfortable with this being in a TestingAPI category exposed in the header > > file, > > > rather than having multiple copy/paste declarations. The .mm implementation > > > will enforce what it sees at compile-time, but this one could be arbitrarily > > > different and still link and run. > > > > What Scott said. Anonymous categories should only be applied if it's > _actually_ > > private to the .mm file the category is in. > > My intention is that it is private. If my intention is incorrect, then I should > move this. Is it wrong for me to intend this to be private? Nothing is really private in Cocoa. If you know the selector, you can send it. Anonymous categories help hide things a bit better, but that's it. The point of anon categories is mostly to hide helper functions from people inspecting the header. But if the same function is shared across several modules, might as well make it public. It's not like the object is in an invalid state when you use it.
LGTM stands. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:82: row:(NSInteger)rowIndex { On 2015/06/12 23:07:54, dschuyler wrote: > On 2015/06/12 22:21:59, Scott Hess wrote: > > I think if they fit, these should align the colon, and only do the four-space > > like this if it doesn't fit. If you consult the style guide and it seems > > ambiguous, ignore me. > > This is formatted the way cl format wants to do it. I realize that is not > really the authority of the style guide, but I'm willing to rely on it for this > case if that's cool. Acknowledged. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 23:07:54, dschuyler wrote: > On 2015/06/12 22:49:20, Scott Hess wrote: > > On 2015/06/12 22:43:01, groby wrote: > > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > > I really really wish that the documentation was more clear about whether > > > > -setDataCell: takes ownership, or adds a reference. This is only correct > if > > > it > > > > takes ownership. You might want to test by having a temporary, and > logging > > > the > > > > results of -retainCount before and after the -setDataCell: call. That's > not > > > > 100% certain, since there could be autorelease pools and the like > involved, > > > but > > > > if the retain count does not change, that probably means that it takes > > > ownership > > > > rather than adding a ref. > > > > > > The docs say "@property (strong) id dataCell". It seems strong is the new > > fancy > > > way to say retain, so it takes ownership. You're safe. > > > > I think that means it takes a reference under non-ARC, which implies that > after > > this statement runs there will be two outstanding references, one of which > > nobody is tracking. > > Does that mean that this should be an autorelease? Yep. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end On 2015/06/12 23:07:54, dschuyler wrote: > On 2015/06/12 22:43:01, groby wrote: > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > I'm losing the ability to follow the discussion, but personally I would be > > > comfortable with this being in a TestingAPI category exposed in the header > > file, > > > rather than having multiple copy/paste declarations. The .mm implementation > > > will enforce what it sees at compile-time, but this one could be arbitrarily > > > different and still link and run. > > > > What Scott said. Anonymous categories should only be applied if it's > _actually_ > > private to the .mm file the category is in. > > My intention is that it is private. If my intention is incorrect, then I should > move this. Is it wrong for me to intend this to be private? Objective-C is very dynamic and many of the checks we do have are based on compile-time annotations. The compiler can verify that your signatures match in the implementation file, but since this file can't see inside that file, it'll just assume that you know what you're doing. So you can get something like a C++ one-definition-rule violation, and nobody helps you find it, and maybe it works at runtime and maybe it doesn't. Chromium convention is to put a TestingAPI category in a header, and then make rude comments if someone later comes along and uses it in production code. Generally Chromium Objective-C classes simply aren't general-purpose enough that anyone ever wants to use your private methods :-).
https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm:123: [column setDataCell:[[OmniboxPopupCell alloc] init]]; On 2015/06/12 23:18:13, Scott Hess wrote: > On 2015/06/12 23:07:54, dschuyler wrote: > > On 2015/06/12 22:49:20, Scott Hess wrote: > > > On 2015/06/12 22:43:01, groby wrote: > > > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > > > I really really wish that the documentation was more clear about whether > > > > > -setDataCell: takes ownership, or adds a reference. This is only > correct > > if > > > > it > > > > > takes ownership. You might want to test by having a temporary, and > > logging > > > > the > > > > > results of -retainCount before and after the -setDataCell: call. That's > > not > > > > > 100% certain, since there could be autorelease pools and the like > > involved, > > > > but > > > > > if the retain count does not change, that probably means that it takes > > > > ownership > > > > > rather than adding a ref. > > > > > > > > The docs say "@property (strong) id dataCell". It seems strong is the new > > > fancy > > > > way to say retain, so it takes ownership. You're safe. > > > > > > I think that means it takes a reference under non-ARC, which implies that > > after > > > this statement runs there will be two outstanding references, one of which > > > nobody is tracking. > > > > Does that mean that this should be an autorelease? > > Yep. Done. https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... File chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm (right): https://codereview.chromium.org/1099403005/diff/700001/chrome/browser/ui/coco... chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix_unittest.mm:14: @end On 2015/06/12 23:18:13, Scott Hess wrote: > On 2015/06/12 23:07:54, dschuyler wrote: > > On 2015/06/12 22:43:01, groby wrote: > > > On 2015/06/12 22:21:59, Scott Hess wrote: > > > > I'm losing the ability to follow the discussion, but personally I would be > > > > comfortable with this being in a TestingAPI category exposed in the header > > > file, > > > > rather than having multiple copy/paste declarations. The .mm > implementation > > > > will enforce what it sees at compile-time, but this one could be > arbitrarily > > > > different and still link and run. > > > > > > What Scott said. Anonymous categories should only be applied if it's > > _actually_ > > > private to the .mm file the category is in. > > > > My intention is that it is private. If my intention is incorrect, then I > should > > move this. Is it wrong for me to intend this to be private? > > Objective-C is very dynamic and many of the checks we do have are based on > compile-time annotations. The compiler can verify that your signatures match in > the implementation file, but since this file can't see inside that file, it'll > just assume that you know what you're doing. So you can get something like a > C++ one-definition-rule violation, and nobody helps you find it, and maybe it > works at runtime and maybe it doesn't. > > Chromium convention is to put a TestingAPI category in a header, and then make > rude comments if someone later comes along and uses it in production code. > Generally Chromium Objective-C classes simply aren't general-purpose enough that > anyone ever wants to use your private methods :-). Done.
The CQ bit was checked by dschuyler@chromium.org
The patchset sent to the CQ was uploaded after l-g-t-m from shrike@chromium.org, groby@chromium.org, shess@chromium.org Link to the patchset: https://codereview.chromium.org/1099403005/#ps770001 (title: "autorelease on column data cell")
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/1099403005/770001
Message was sent while issue was closed.
Committed patchset #40 (id:770001)
Message was sent while issue was closed.
Patchset 40 (id:??) landed as https://crrev.com/aa726aa5c1121fc55c9cf5b40e18ca1d0a9b7337 Cr-Commit-Position: refs/heads/master@{#334305} |