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

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: Merge form master Created 5 years, 6 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 - (instancetype)init {
23 if ((self = [super init])) {
24 hoveredIndex_ = -1;
25 }
26 return self;
27 }
28
29 - (instancetype)initWithMatchResults:(const AutocompleteResult&)result
30 popupView:(const OmniboxPopupViewMac&)popupView
31 answerImage:(NSImage*)answerImage {
32 if ((self = [super init])) {
33 hoveredIndex_ = -1;
34 array_.reset([[NSMutableArray alloc] init]);
35 CGFloat max_match_contents_width = 0.0f;
36 CGFloat contents_offset = -1.0f;
37 for (const AutocompleteMatch& match : result) {
38 base::scoped_nsobject<OmniboxPopupCellData> cellData(
39 [[OmniboxPopupCellData alloc]
40 initWithMatch:match
41 image:popupView.ImageForMatch(match)]);
42 if (match.answer && answerImage)
groby-ooo-7-16 2015/06/11 01:22:18 Again, this modifies something that's technically
dschuyler 2015/06/11 22:34:22 Done.
43 [cellData setAnswerImage:answerImage];
44 [array_ addObject:cellData];
45 if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) {
46 max_match_contents_width = std::max(max_match_contents_width,
47 [cellData getMatchContentsWidth]);
48 if (contents_offset < 0.0f)
49 contents_offset = [OmniboxPopupCell computeContentsOffset:match];
50 [cellData setContentsOffset:contents_offset];
51 }
52 }
53
54 for (const OmniboxPopupCellData* cellData : array_.get()) {
55 [cellData setMaxMatchContentsWidth:max_match_contents_width];
groby-ooo-7-16 2015/06/11 01:22:18 Grumblemumble immutable grumblemumble. (We can ge
dschuyler 2015/06/11 22:34:23 Done.
56 }
57 }
58 return self;
59 }
60
61 - (instancetype)initWithArray:(NSMutableArray*)array {
62 if ((self = [super init])) {
63 hoveredIndex_ = -1;
64 array_.reset([array retain]);
groby-ooo-7-16 2015/06/11 01:22:17 Usually, if you init with a mutable array, you cop
Scott Hess - ex-Googler 2015/06/11 21:52:02 I think -copy returns a reference, so you just do:
dschuyler 2015/06/11 22:34:22 I'm having trouble following this, is this a misty
dschuyler 2015/06/11 22:34:23 Done.
Scott Hess - ex-Googler 2015/06/11 22:36:19 Yeah, I think there was a missing n't or im in the
dschuyler 2015/06/12 00:43:26 I think we still want the data member to be a muta
Scott Hess - ex-Googler 2015/06/12 20:21:32 I think maybe you're wavering back and forth based
dschuyler 2015/06/12 21:44:30 Thanks. I'm hoping I'm closer now. The array is
groby-ooo-7-16 2015/06/12 22:24:30 Yes, please. I now my future self, and she'll make
65 }
66 return self;
67 }
68
69 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
70 return [array_ count];
71 }
72
73 - (id)tableView:(NSTableView*)tableView
74 objectValueForTableColumn:(NSTableColumn*)tableColumn
75 row:(NSInteger)rowIndex {
76 return nil;
groby-ooo-7-16 2015/06/11 01:22:18 As discussed in earlier CLs: This should return th
dschuyler 2015/06/11 22:34:23 Done.
77 }
78
79 - (void)tableView:(NSTableView*)aTableView
80 setObjectValue:(id)anObject
81 forTableColumn:(NSTableColumn*)aTableColumn
82 row:(NSInteger)rowIndex {
83 }
groby-ooo-7-16 2015/06/11 01:22:17 NOTREACHED, please, since we'll never modify value
dschuyler 2015/06/11 22:34:22 Done.
84
85 - (void)tableView:(NSTableView*)tableView
86 willDisplayCell:(id)cell
87 forTableColumn:(NSTableColumn*)tableColumn
88 row:(NSInteger)rowIndex {
89 OmniboxPopupCell* popupCell =
90 base::mac::ObjCCastStrict<OmniboxPopupCell>(cell);
91 [popupCell setObjectValue:[array_ objectAtIndex:rowIndex]];
groby-ooo-7-16 2015/06/11 01:22:17 [popupCell setObjectValue:[array_ objectAtIndex:ro
dschuyler 2015/06/11 22:34:22 Done.
92 [popupCell
93 setState:([tableView selectedRow] == rowIndex) ? NSOnState : NSOffState];
94 [popupCell highlight:(hoveredIndex_ == rowIndex)
95 withFrame:[tableView bounds]
96 inView:tableView];
97 }
98
99 - (NSInteger)highlightedRow {
100 return hoveredIndex_;
101 }
102
103 - (void)highlightRowAt:(NSInteger)rowIndex {
groby-ooo-7-16 2015/06/11 01:22:18 - (void)setHighlightedRow:(NSInteger)rowIndex set
dschuyler 2015/06/11 22:34:23 Done.
104 hoveredIndex_ = rowIndex;
105 }
106
107 - (CGFloat)tableView:(NSTableView*)tableView heightOfRow:(NSInteger)row {
108 return [[array_ objectAtIndex:row] rowHeight];
109 }
110
111 @end
112
113 @interface OmniboxPopupMatrix ()
18 - (void)resetTrackingArea; 114 - (void)resetTrackingArea;
19 - (void)highlightRowAt:(NSInteger)rowIndex;
20 - (void)highlightRowUnder:(NSEvent*)theEvent; 115 - (void)highlightRowUnder:(NSEvent*)theEvent;
21 - (BOOL)selectCellForEvent:(NSEvent*)theEvent; 116 - (BOOL)selectCellForEvent:(NSEvent*)theEvent;
22 @end 117 @end
23 118
24 @implementation OmniboxPopupMatrix 119 @implementation OmniboxPopupMatrix
25 120
26 - (id)initWithObserver:(OmniboxPopupMatrixObserver*)observer { 121 - (instancetype)initWithObserver:(OmniboxPopupMatrixObserver*)observer {
27 if ((self = [super initWithFrame:NSZeroRect])) { 122 if ((self = [super initWithFrame:NSZeroRect])) {
28 observer_ = observer; 123 observer_ = observer;
29 [self setCellClass:[OmniboxPopupCell class]]; 124
125 base::scoped_nsobject<NSTableColumn> column(
126 [[NSTableColumn alloc] initWithIdentifier:@"MainCell"]);
groby-ooo-7-16 2015/06/11 01:22:17 Well, it'd be the "MainColumn" if that's the ID we
dschuyler 2015/06/11 22:34:22 Done.
127 [column setDataCell:[[OmniboxPopupCell alloc] init]];
128 [self addTableColumn:column];
30 129
31 // Cells pack with no spacing. 130 // Cells pack with no spacing.
32 [self setIntercellSpacing:NSMakeSize(0.0, 0.0)]; 131 [self setIntercellSpacing:NSMakeSize(0.0, 0.0)];
33 132
34 [self setDrawsBackground:YES]; 133 [self setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleNone];
35 [self setBackgroundColor:[NSColor controlBackgroundColor]]; 134 [self setBackgroundColor:[NSColor controlBackgroundColor]];
36 [self renewRows:0 columns:1];
37 [self setAllowsEmptySelection:YES]; 135 [self setAllowsEmptySelection:YES];
38 [self setMode:NSRadioModeMatrix]; 136 [self deselectAll:self];
39 [self deselectAllCells];
40 137
41 [self resetTrackingArea]; 138 [self resetTrackingArea];
42 } 139 }
43 return self; 140 return self;
44 } 141 }
45 142
143 - (OmniboxPopupTableController*)controller {
144 return base::mac::ObjCCastStrict<OmniboxPopupTableController>(
145 [self delegate]);
146 }
147
46 - (void)setObserver:(OmniboxPopupMatrixObserver*)observer { 148 - (void)setObserver:(OmniboxPopupMatrixObserver*)observer {
47 observer_ = observer; 149 observer_ = observer;
48 } 150 }
49 151
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 { 152 - (void)updateTrackingAreas {
62 [self resetTrackingArea]; 153 [self resetTrackingArea];
63 [super updateTrackingAreas]; 154 [super updateTrackingAreas];
64 } 155 }
65 156
66 // Callbacks from tracking area. 157 // Callbacks from tracking area.
67 - (void)mouseEntered:(NSEvent*)theEvent { 158 - (void)mouseEntered:(NSEvent*)theEvent {
68 [self highlightRowUnder:theEvent]; 159 [self highlightRowUnder:theEvent];
69 } 160 }
70 161
71 - (void)mouseMoved:(NSEvent*)theEvent { 162 - (void)mouseMoved:(NSEvent*)theEvent {
72 [self highlightRowUnder:theEvent]; 163 [self highlightRowUnder:theEvent];
73 } 164 }
74 165
75 - (void)mouseExited:(NSEvent*)theEvent { 166 - (void)mouseExited:(NSEvent*)theEvent {
76 [self highlightRowAt:-1]; 167 [[self controller] highlightRowAt:-1];
77 } 168 }
78 169
79 // The tracking area events aren't forwarded during a drag, so handle 170 // The tracking area events aren't forwarded during a drag, so handle
80 // highlighting manually for middle-click and middle-drag. 171 // highlighting manually for middle-click and middle-drag.
81 - (void)otherMouseDown:(NSEvent*)theEvent { 172 - (void)otherMouseDown:(NSEvent*)theEvent {
82 if ([theEvent buttonNumber] == kMiddleButtonNumber) { 173 if ([theEvent buttonNumber] == kMiddleButtonNumber) {
83 [self highlightRowUnder:theEvent]; 174 [self highlightRowUnder:theEvent];
84 } 175 }
85 [super otherMouseDown:theEvent]; 176 [super otherMouseDown:theEvent];
86 } 177 }
87 178
88 - (void)otherMouseDragged:(NSEvent*)theEvent { 179 - (void)otherMouseDragged:(NSEvent*)theEvent {
89 if ([theEvent buttonNumber] == kMiddleButtonNumber) { 180 if ([theEvent buttonNumber] == kMiddleButtonNumber) {
90 [self highlightRowUnder:theEvent]; 181 [self highlightRowUnder:theEvent];
91 } 182 }
92 [super otherMouseDragged:theEvent]; 183 [super otherMouseDragged:theEvent];
93 } 184 }
94 185
95 - (void)otherMouseUp:(NSEvent*)theEvent { 186 - (void)otherMouseUp:(NSEvent*)theEvent {
96 // Only intercept middle button. 187 // Only intercept middle button.
97 if ([theEvent buttonNumber] != kMiddleButtonNumber) { 188 if ([theEvent buttonNumber] != kMiddleButtonNumber) {
98 [super otherMouseUp:theEvent]; 189 [super otherMouseUp:theEvent];
99 return; 190 return;
100 } 191 }
101 192
102 // -otherMouseDragged: should always have been called at this location, but 193 // -otherMouseDragged: should always have been called at this location, but
103 // make sure the user is getting the right feedback. 194 // make sure the user is getting the right feedback.
104 [self highlightRowUnder:theEvent]; 195 [self highlightRowUnder:theEvent];
105 196
106 const NSInteger highlightedRow = [self highlightedRow]; 197 const NSInteger highlightedRow = [[self controller] highlightedRow];
107 if (highlightedRow != -1) { 198 if (highlightedRow != -1) {
108 DCHECK(observer_); 199 DCHECK(observer_);
109 observer_->OnMatrixRowMiddleClicked(self, highlightedRow); 200 observer_->OnMatrixRowMiddleClicked(self, highlightedRow);
110 } 201 }
111 } 202 }
112 203
113 // Track the mouse until released, keeping the cell under the mouse selected. 204 // 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 205 // 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. 206 // the mouse is released over a cell, call the delegate to open the row's URL.
116 - (void)mouseDown:(NSEvent*)theEvent { 207 - (void)mouseDown:(NSEvent*)theEvent {
117 NSCell* selectedCell = [self selectedCell]; 208 NSCell* selectedCell = [self selectedCell];
118 209
119 // Clear any existing highlight. 210 // Clear any existing highlight.
120 [self highlightRowAt:-1]; 211 [[self controller] highlightRowAt:-1];
121 212
122 do { 213 do {
123 if (![self selectCellForEvent:theEvent]) { 214 if (![self selectCellForEvent:theEvent]) {
124 [self selectCell:selectedCell]; 215 [self selectCell:selectedCell];
125 } 216 }
126 217
127 const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask; 218 const NSUInteger mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
128 theEvent = [[self window] nextEventMatchingMask:mask]; 219 theEvent = [[self window] nextEventMatchingMask:mask];
129 } while ([theEvent type] == NSLeftMouseDragged); 220 } while ([theEvent type] == NSLeftMouseDragged);
130 221
131 // Do not message the delegate if released outside view. 222 // Do not message the delegate if released outside view.
132 if (![self selectCellForEvent:theEvent]) { 223 if (![self selectCellForEvent:theEvent]) {
133 [self selectCell:selectedCell]; 224 [self selectCell:selectedCell];
134 } else { 225 } else {
135 const NSInteger selectedRow = [self selectedRow]; 226 const NSInteger selectedRow = [self selectedRow];
136 227
137 // No row could be selected if the model failed to update. 228 // No row could be selected if the model failed to update.
138 if (selectedRow == -1) { 229 if (selectedRow == -1) {
139 NOTREACHED(); 230 NOTREACHED();
140 return; 231 return;
141 } 232 }
142 233
143 DCHECK(observer_); 234 DCHECK(observer_);
144 observer_->OnMatrixRowClicked(self, selectedRow); 235 observer_->OnMatrixRowClicked(self, selectedRow);
145 } 236 }
146 } 237 }
147 238
239 - (void)selectRowIndex:(NSInteger)rowIndex {
240 NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:rowIndex];
241 [self selectRowIndexes:indexSet byExtendingSelection:NO];
242 }
243
244 - (NSInteger)highlightedRow {
245 return [[self controller] highlightedRow];
246 }
247
248 - (void)setController:(OmniboxPopupTableController*)controller {
249 matrixController_.reset([controller retain]);
250 [self setDelegate:controller];
251 [self setDataSource:controller];
252 [self reloadData];
253 }
254
148 - (void)resetTrackingArea { 255 - (void)resetTrackingArea {
149 if (trackingArea_.get()) 256 if (trackingArea_.get())
150 [self removeTrackingArea:trackingArea_.get()]; 257 [self removeTrackingArea:trackingArea_.get()];
151 258
152 trackingArea_.reset([[CrTrackingArea alloc] 259 trackingArea_.reset([[CrTrackingArea alloc]
153 initWithRect:[self frame] 260 initWithRect:[self frame]
154 options:NSTrackingMouseEnteredAndExited | 261 options:NSTrackingMouseEnteredAndExited |
155 NSTrackingMouseMoved | 262 NSTrackingMouseMoved |
156 NSTrackingActiveInActiveApp | 263 NSTrackingActiveInActiveApp |
157 NSTrackingInVisibleRect 264 NSTrackingInVisibleRect
158 owner:self 265 owner:self
159 userInfo:nil]); 266 userInfo:nil]);
160 [self addTrackingArea:trackingArea_.get()]; 267 [self addTrackingArea:trackingArea_.get()];
161 } 268 }
162 269
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 { 270 - (void)highlightRowUnder:(NSEvent*)theEvent {
174 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 271 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
175 NSInteger row, column; 272 NSInteger oldRow = [[self controller] highlightedRow];
176 if ([self getRow:&row column:&column forPoint:point]) { 273 NSInteger newRow = [self rowAtPoint:point];
177 [self highlightRowAt:row]; 274 if (oldRow != newRow) {
178 } else { 275 [[self controller] highlightRowAt:newRow];
179 [self highlightRowAt:-1]; 276 [self setNeedsDisplayInRect:[self rectOfRow:oldRow]];
277 [self setNeedsDisplayInRect:[self rectOfRow:newRow]];
180 } 278 }
181 } 279 }
182 280
183 // Select cell under |theEvent|, returning YES if a selection is made.
184 - (BOOL)selectCellForEvent:(NSEvent*)theEvent { 281 - (BOOL)selectCellForEvent:(NSEvent*)theEvent {
185 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 282 NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
186 283
187 NSInteger row, column; 284 NSInteger row = [self rowAtPoint:point];
188 if ([self getRow:&row column:&column forPoint:point]) { 285 [self selectRowIndex:row];
189 DCHECK_EQ(column, 0); 286 if (row != -1) {
190 DCHECK(observer_); 287 DCHECK(observer_);
191 observer_->OnMatrixRowSelected(self, row); 288 observer_->OnMatrixRowSelected(self, row);
192 return YES; 289 return YES;
193 } 290 }
194 return NO; 291 return NO;
195 } 292 }
196 293
197 @end 294 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698