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

Side by Side Diff: chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.mm

Issue 1099403005: [AiS] changing mac omnibox suggestions form NSMatrix to NSTableView (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removed withView arg from highlightRowAt Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h" 5 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_matrix.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/mac/foundation_util.h"
8 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" 9 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h"
10 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
11 #include "components/omnibox/autocomplete_result.h"
9 12
10 namespace { 13 namespace {
11 14
12 // NSEvent -buttonNumber for middle mouse button. 15 // NSEvent -buttonNumber for middle mouse button.
13 const NSInteger kMiddleButtonNumber = 2; 16 const NSInteger kMiddleButtonNumber = 2;
14 17
15 } // namespace 18 } // namespace
16 19
17 @interface OmniboxPopupMatrix() 20 @implementation OmniboxPopupTableController
21
22 - (id)init {
23 if ((self = [super init])) {
24 hoveredIndex_ = -1;
25 }
26 return self;
27 }
28
29 - (id)initWithMatchResults:(const AutocompleteResult&)result
30 popupView:(const OmniboxPopupViewMac&)popupView {
31 if ((self = [super init])) {
32 hoveredIndex_ = -1;
33 // Load the results into the popup's matrix.
34 const size_t start_match = result.ShouldHideTopMatch() ? 1 : 0;
35 const size_t rows = result.size() - start_match;
36 DCHECK_GT(rows, 0U);
Scott Hess - ex-Googler 2015/05/21 20:40:27 IMHO this would be better as: DCHECK_GT(result.
dschuyler 2015/05/26 18:40:20 Done.
37 base::scoped_nsobject<NSMutableArray> array([[NSMutableArray alloc] init]);
groby-ooo-7-16 2015/05/21 03:01:48 Why not keep it directly in array_?
Scott Hess - ex-Googler 2015/05/21 20:40:27 array_ is NSArray. Which makes me wonder if array
dschuyler 2015/05/26 18:40:20 If there are good reasons to choose style A or B w
dschuyler 2015/05/26 18:40:20 For reasons Scott gives below. :)
groby-ooo-7-16 2015/05/26 21:23:22 Acknowledged.
Scott Hess - ex-Googler 2015/05/29 18:00:26 This is like const functions in C++, where there's
dschuyler 2015/06/09 01:30:46 Thanks Done.
38 CGFloat max_match_contents_width = 0.0f;
39 CGFloat contents_offset = -1.0f;
40 for (size_t ii = 0; ii < rows; ++ii) {
groby-ooo-7-16 2015/05/21 03:01:48 Please don't perpetuate ii :) Best, don't even loo
Scott Hess - ex-Googler 2015/05/21 04:46:36 Yeah, that's some ancient habit of mine which has
dschuyler 2015/05/26 18:40:20 Acknowledged.
dschuyler 2015/05/26 18:40:20 The <should hide top match> stuff is a discontinue
groby-ooo-7-16 2015/05/26 21:23:22 If you can do that as a prior CL and rebase this C
dschuyler 2015/05/28 20:34:22 That CL is now started.
dschuyler 2015/06/10 20:48:31 Done.
41 const AutocompleteMatch& match = result.match_at(ii + start_match);
42 NSImage* image = popupView.ImageForMatch(match);
groby-ooo-7-16 2015/05/21 03:01:48 Bleh. I hate we have to pass the popupView. I wond
dschuyler 2015/05/26 18:40:21 Which direction is the right way to go for this pa
groby-ooo-7-16 2015/05/26 21:23:22 Yes, I think that's fine. It's not perfect, but it
dschuyler 2015/05/28 20:34:22 Bug entered 492896
43 base::scoped_nsobject<OmniboxPopupCellData> cellData(
44 [[OmniboxPopupCellData alloc] initWithMatch:match image:image]);
45 [array addObject:cellData];
groby-ooo-7-16 2015/05/21 03:01:48 You _could_ just move the alloc/initWithMatch call
Scott Hess - ex-Googler 2015/05/21 20:40:27 Someone needs to own the +alloc ref, though.
groby-ooo-7-16 2015/05/22 05:03:07 Yep: [array addObject:[[[OmniboxPopupCellData all
Scott Hess - ex-Googler 2015/05/22 05:17:58 I think that means you can do what you wish, eithe
dschuyler 2015/05/26 18:40:21 Acknowledged.
46 if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
47 max_match_contents_width = std::max(max_match_contents_width,
groby-ooo-7-16 2015/05/21 03:01:48 So max_match_contents_width stays 0 unless you hav
Scott Hess - ex-Googler 2015/05/21 20:40:27 Yeah, this is a thing we ground on about in the or
dschuyler 2015/05/26 18:40:20 Acknowledged.
dschuyler 2015/05/26 18:40:20 Acknowledged.
dschuyler 2015/05/26 18:40:21 I'd like to leave the TAIL stuff unchanged until A
groby-ooo-7-16 2015/05/26 21:23:22 Acknowledged.
48 [cellData getMatchContentsWidth]);
49 if (contents_offset < 0.0f) {
Scott Hess - ex-Googler 2015/05/21 20:40:27 Drop the {} here.
dschuyler 2015/05/26 18:40:20 Done.
50 contents_offset = [OmniboxPopupCell computeContentsOffset:match];
51 }
52 [cellData setContentsOffset:contents_offset];
53 }
54 }
55
56 for (size_t ii = 0; ii < rows; ++ii) {
groby-ooo-7-16 2015/05/21 03:01:48 for (OmniboxPopupCellData* cellData : array) [ce
dschuyler 2015/05/26 18:40:20 Done.
57 OmniboxPopupCellData* cellData = [array objectAtIndex:ii];
58 [cellData setMaxMatchContentsWidth:max_match_contents_width];
59 }
60 array_.reset([array retain]);
61 }
62 return self;
63 }
64
65 - (id)initWithArray:(NSArray*)array {
Scott Hess - ex-Googler 2015/05/21 20:40:27 instancetype.
dschuyler 2015/05/26 18:40:20 Done.
66 if ((self = [super init])) {
67 hoveredIndex_ = -1;
68 array_.reset([array retain]);
69 }
70 return self;
71 }
72
73 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
74 return [array_ count];
75 }
76
77 - (id)tableView:(NSTableView*)tableView
78 objectValueForTableColumn:(NSTableColumn*)tableColumn
79 row:(NSInteger)rowIndex {
80 return nil;
81 }
82
83 - (void)tableView:(NSTableView*)aTableView
84 setObjectValue:(id)anObject
85 forTableColumn:(NSTableColumn*)aTableColumn
86 row:(NSInteger)rowIndex {
87 }
88
89 - (void)tableView:(NSTableView*)tableView
90 willDisplayCell:(id)cell
91 forTableColumn:(NSTableColumn*)tableColumn
92 row:(NSInteger)rowIndex {
93 OmniboxPopupCell* popupCell =
94 base::mac::ObjCCastStrict<OmniboxPopupCell>(cell);
95 [popupCell setRepresentedObject:[[array_ objectAtIndex:rowIndex] retain]];
96 [popupCell
97 setState:([tableView selectedRow] == rowIndex) ? NSOnState : NSOffState];
98 [popupCell highlight:(hoveredIndex_ == rowIndex)
99 withFrame:[tableView bounds]
100 inView:tableView];
101 }
102
103 - (NSInteger)highlightedRow {
104 return hoveredIndex_;
105 }
106
107 - (void)highlightRowAt:(NSInteger)rowIndex {
108 hoveredIndex_ = rowIndex;
109 }
110
111 - (CGFloat)tableView:(NSTableView*)tableView heightOfRow:(NSInteger)row {
112 OmniboxPopupCellData* cellData = [array_ objectAtIndex:row];
groby-ooo-7-16 2015/05/21 03:01:48 chaining methods would be preferred - no need to h
dschuyler 2015/05/26 18:40:20 Done.
113 return [cellData rowHeight];
groby-ooo-7-16 2015/05/21 03:01:48 Just a general note on tables, no need to implemen
dschuyler 2015/05/26 18:40:21 Acknowledged.
114 }
115
116 @end
117
118 @interface OmniboxPopupMatrix ()
18 - (void)resetTrackingArea; 119 - (void)resetTrackingArea;
19 - (void)highlightRowAt:(NSInteger)rowIndex;
20 - (void)highlightRowUnder:(NSEvent*)theEvent; 120 - (void)highlightRowUnder:(NSEvent*)theEvent;
21 - (BOOL)selectCellForEvent:(NSEvent*)theEvent; 121 - (BOOL)selectCellForEvent:(NSEvent*)theEvent;
22 @end 122 @end
23 123
24 @implementation OmniboxPopupMatrix 124 @implementation OmniboxPopupMatrix
25 125
26 - (id)initWithObserver:(OmniboxPopupMatrixObserver*)observer { 126 - (id)initWithObserver:(OmniboxPopupMatrixObserver*)observer {
27 if ((self = [super initWithFrame:NSZeroRect])) { 127 if ((self = [super initWithFrame:NSZeroRect])) {
28 observer_ = observer; 128 observer_ = observer;
29 [self setCellClass:[OmniboxPopupCell class]]; 129
130 base::scoped_nsobject<NSTableColumn> column(
131 [[NSTableColumn alloc] initWithIdentifier:@"MainCell"]);
132 base::scoped_nsobject<OmniboxPopupCell> columnCell(
133 [[OmniboxPopupCell alloc] init]);
groby-ooo-7-16 2015/05/21 03:01:48 Again, skip the scoped temp and chain methods.
Scott Hess - ex-Googler 2015/05/21 20:40:27 I think this one also leaves an additional ref unl
groby-ooo-7-16 2015/05/22 05:03:07 Acknowledged.
dschuyler 2015/05/26 18:40:20 Acknowledged.
dschuyler 2015/05/26 18:40:21 Done.
134 [column setDataCell:columnCell];
135 [self addTableColumn:column];
30 136
31 // Cells pack with no spacing. 137 // Cells pack with no spacing.
32 [self setIntercellSpacing:NSMakeSize(0.0, 0.0)]; 138 [self setIntercellSpacing:NSMakeSize(0.0, 0.0)];
33 139
34 [self setDrawsBackground:YES]; 140 [self setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];
35 [self setBackgroundColor:[NSColor controlBackgroundColor]]; 141 [self setBackgroundColor:[NSColor controlBackgroundColor]];
36 [self renewRows:0 columns:1];
37 [self setAllowsEmptySelection:YES]; 142 [self setAllowsEmptySelection:YES];
38 [self setMode:NSRadioModeMatrix]; 143 [self deselectAll:self];
39 [self deselectAllCells];
40 144
41 [self resetTrackingArea]; 145 [self resetTrackingArea];
42 } 146 }
43 return self; 147 return self;
44 } 148 }
45 149
150 - (OmniboxPopupTableController*)controller {
151 return base::mac::ObjCCastStrict<OmniboxPopupTableController>(
152 [self delegate]);
153 }
154
46 - (void)setObserver:(OmniboxPopupMatrixObserver*)observer { 155 - (void)setObserver:(OmniboxPopupMatrixObserver*)observer {
47 observer_ = observer; 156 observer_ = observer;
48 } 157 }
49 158
50 - (NSInteger)highlightedRow {
51 NSArray* cells = [self cells];
52 const NSUInteger count = [cells count];
53 for(NSUInteger i = 0; i < count; ++i) {
54 if ([[cells objectAtIndex:i] isHighlighted]) {
55 return i;
56 }
57 }
58 return -1;
59 }
60
61 - (void)updateTrackingAreas { 159 - (void)updateTrackingAreas {
62 [self resetTrackingArea]; 160 [self resetTrackingArea];
63 [super updateTrackingAreas]; 161 [super updateTrackingAreas];
64 } 162 }
65 163
66 // Callbacks from tracking area. 164 // Callbacks from tracking area.
67 - (void)mouseEntered:(NSEvent*)theEvent { 165 - (void)mouseEntered:(NSEvent*)theEvent {
68 [self highlightRowUnder:theEvent]; 166 [self highlightRowUnder:theEvent];
69 } 167 }
70 168
71 - (void)mouseMoved:(NSEvent*)theEvent { 169 - (void)mouseMoved:(NSEvent*)theEvent {
72 [self highlightRowUnder:theEvent]; 170 [self highlightRowUnder:theEvent];
73 } 171 }
74 172
75 - (void)mouseExited:(NSEvent*)theEvent { 173 - (void)mouseExited:(NSEvent*)theEvent {
76 [self highlightRowAt:-1]; 174 [[self controller] highlightRowAt:-1];
77 } 175 }
78 176
79 // The tracking area events aren't forwarded during a drag, so handle 177 // The tracking area events aren't forwarded during a drag, so handle
80 // highlighting manually for middle-click and middle-drag. 178 // highlighting manually for middle-click and middle-drag.
81 - (void)otherMouseDown:(NSEvent*)theEvent { 179 - (void)otherMouseDown:(NSEvent*)theEvent {
82 if ([theEvent buttonNumber] == kMiddleButtonNumber) { 180 if ([theEvent buttonNumber] == kMiddleButtonNumber) {
83 [self highlightRowUnder:theEvent]; 181 [self highlightRowUnder:theEvent];
84 } 182 }
85 [super otherMouseDown:theEvent]; 183 [super otherMouseDown:theEvent];
86 } 184 }
87 185
88 - (void)otherMouseDragged:(NSEvent*)theEvent { 186 - (void)otherMouseDragged:(NSEvent*)theEvent {
89 if ([theEvent buttonNumber] == kMiddleButtonNumber) { 187 if ([theEvent buttonNumber] == kMiddleButtonNumber) {
90 [self highlightRowUnder:theEvent]; 188 [self highlightRowUnder:theEvent];
91 } 189 }
92 [super otherMouseDragged:theEvent]; 190 [super otherMouseDragged:theEvent];
93 } 191 }
94 192
95 - (void)otherMouseUp:(NSEvent*)theEvent { 193 - (void)otherMouseUp:(NSEvent*)theEvent {
96 // Only intercept middle button. 194 // Only intercept middle button.
97 if ([theEvent buttonNumber] != kMiddleButtonNumber) { 195 if ([theEvent buttonNumber] != kMiddleButtonNumber) {
98 [super otherMouseUp:theEvent]; 196 [super otherMouseUp:theEvent];
99 return; 197 return;
100 } 198 }
101 199
102 // -otherMouseDragged: should always have been called at this location, but 200 // -otherMouseDragged: should always have been called at this location, but
103 // make sure the user is getting the right feedback. 201 // make sure the user is getting the right feedback.
104 [self highlightRowUnder:theEvent]; 202 [self highlightRowUnder:theEvent];
105 203
106 const NSInteger highlightedRow = [self highlightedRow]; 204 const NSInteger highlightedRow = [[self controller] highlightedRow];
107 if (highlightedRow != -1) { 205 if (highlightedRow != -1) {
108 DCHECK(observer_); 206 DCHECK(observer_);
109 observer_->OnMatrixRowMiddleClicked(self, highlightedRow); 207 observer_->OnMatrixRowMiddleClicked(self, highlightedRow);
110 } 208 }
111 } 209 }
112 210
113 // Track the mouse until released, keeping the cell under the mouse selected. 211 // Track the mouse until released, keeping the cell under the mouse selected.
114 // If the mouse wanders off-view, revert to the originally-selected cell. If 212 // If the mouse wanders off-view, revert to the originally-selected cell. If
115 // the mouse is released over a cell, call the delegate to open the row's URL. 213 // the mouse is released over a cell, call the delegate to open the row's URL.
116 - (void)mouseDown:(NSEvent*)theEvent { 214 - (void)mouseDown:(NSEvent*)theEvent {
117 NSCell* selectedCell = [self selectedCell]; 215 NSCell* selectedCell = [self selectedCell];
118 216
119 // Clear any existing highlight. 217 // Clear any existing highlight.
120 [self highlightRowAt:-1]; 218 [[self controller] highlightRowAt:-1];
121 219
122 do { 220 do {
123 if (![self selectCellForEvent:theEvent]) { 221 if (![self selectCellForEvent:theEvent]) {
124 [self selectCell:selectedCell]; 222 [self selectCell:selectedCell];
125 } 223 }
126 224
127 const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask; 225 const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
128 theEvent = [[self window] nextEventMatchingMask:mask]; 226 theEvent = [[self window] nextEventMatchingMask:mask];
129 } while ([theEvent type] == NSLeftMouseDragged); 227 } while ([theEvent type] == NSLeftMouseDragged);
130 228
131 // Do not message the delegate if released outside view. 229 // Do not message the delegate if released outside view.
132 if (![self selectCellForEvent:theEvent]) { 230 if (![self selectCellForEvent:theEvent]) {
133 [self selectCell:selectedCell]; 231 [self selectCell:selectedCell];
134 } else { 232 } else {
135 const NSInteger selectedRow = [self selectedRow]; 233 const NSInteger selectedRow = [self selectedRow];
136 234
137 // No row could be selected if the model failed to update. 235 // No row could be selected if the model failed to update.
138 if (selectedRow == -1) { 236 if (selectedRow == -1) {
139 NOTREACHED(); 237 NOTREACHED();
140 return; 238 return;
141 } 239 }
142 240
143 DCHECK(observer_); 241 DCHECK(observer_);
144 observer_->OnMatrixRowClicked(self, selectedRow); 242 observer_->OnMatrixRowClicked(self, selectedRow);
145 } 243 }
146 } 244 }
147 245
246 - (void)selectRowIndex:(NSInteger)rowIndex {
247 NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:rowIndex];
248 [self selectRowIndexes:indexSet byExtendingSelection:NO];
249 }
250
251 - (NSInteger)highlightedRow {
252 return [[self controller] highlightedRow];
253 }
254
255 - (void)setController:(OmniboxPopupTableController*)controller {
256 [self setDelegate:controller];
257 [self setDataSource:controller];
258 [self reloadData];
259 }
260
148 - (void)resetTrackingArea { 261 - (void)resetTrackingArea {
149 if (trackingArea_.get()) 262 if (trackingArea_.get())
150 [self removeTrackingArea:trackingArea_.get()]; 263 [self removeTrackingArea:trackingArea_.get()];
151 264
152 trackingArea_.reset([[CrTrackingArea alloc] 265 trackingArea_.reset([[CrTrackingArea alloc]
153 initWithRect:[self frame] 266 initWithRect:[self frame]
154 options:NSTrackingMouseEnteredAndExited | 267 options:NSTrackingMouseEnteredAndExited |
155 NSTrackingMouseMoved | 268 NSTrackingMouseMoved |
156 NSTrackingActiveInActiveApp | 269 NSTrackingActiveInActiveApp |
157 NSTrackingInVisibleRect 270 NSTrackingInVisibleRect
158 owner:self 271 owner:self
159 userInfo:nil]); 272 userInfo:nil]);
160 [self addTrackingArea:trackingArea_.get()]; 273 [self addTrackingArea:trackingArea_.get()];
161 } 274 }
162 275
163 - (void)highlightRowAt:(NSInteger)rowIndex {
164 // highlightCell will be nil if rowIndex is out of range, so no cell will be
165 // highlighted.
166 NSCell* highlightCell = [self cellAtRow:rowIndex column:0];
167
168 for (NSCell* cell in [self cells]) {
169 [cell setHighlighted:(cell == highlightCell)];
170 }
171 }
172
173 - (void)highlightRowUnder:(NSEvent*)theEvent { 276 - (void)highlightRowUnder:(NSEvent*)theEvent {
174 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 277 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
175 NSInteger row, column; 278 NSInteger oldRow = [[self controller] highlightedRow];
176 if ([self getRow:&row column:&column forPoint:point]) { 279 NSInteger newRow = [self rowAtPoint:point];
177 [self highlightRowAt:row]; 280 if (oldRow != newRow) {
178 } else { 281 [[self controller] highlightRowAt:newRow];
179 [self highlightRowAt:-1]; 282 [self setNeedsDisplayInRect:[self rectOfRow:oldRow]];
283 [self setNeedsDisplayInRect:[self rectOfRow:newRow]];
180 } 284 }
181 } 285 }
182 286
183 // Select cell under |theEvent|, returning YES if a selection is made.
184 - (BOOL)selectCellForEvent:(NSEvent*)theEvent { 287 - (BOOL)selectCellForEvent:(NSEvent*)theEvent {
185 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 288 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
186 289
187 NSInteger row, column; 290 NSInteger row = [self rowAtPoint:point];
188 if ([self getRow:&row column:&column forPoint:point]) { 291 [self selectRowIndex:row];
189 DCHECK_EQ(column, 0); 292 if (row != -1) {
190 DCHECK(observer_); 293 DCHECK(observer_);
191 observer_->OnMatrixRowSelected(self, row); 294 observer_->OnMatrixRowSelected(self, row);
192 return YES; 295 return YES;
193 } 296 }
194 return NO; 297 return NO;
195 } 298 }
196 299
197 @end 300 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698