OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h" | 5 #include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
58 DCHECK(edit_model); | 58 DCHECK(edit_model); |
59 } | 59 } |
60 | 60 |
61 OmniboxPopupViewMac::~OmniboxPopupViewMac() { | 61 OmniboxPopupViewMac::~OmniboxPopupViewMac() { |
62 // Destroy the popup model before this object is destroyed, because | 62 // Destroy the popup model before this object is destroyed, because |
63 // it can call back to us in the destructor. | 63 // it can call back to us in the destructor. |
64 model_.reset(); | 64 model_.reset(); |
65 | 65 |
66 // Break references to |this| because the popup may not be | 66 // Break references to |this| because the popup may not be |
67 // deallocated immediately. | 67 // deallocated immediately. |
68 [matrix_ setDelegate:NULL]; | 68 [matrix_ setTheDelegate:NULL]; |
69 } | 69 } |
70 | 70 |
71 bool OmniboxPopupViewMac::IsOpen() const { | 71 bool OmniboxPopupViewMac::IsOpen() const { |
72 return popup_ != nil; | 72 return popup_ != nil; |
73 } | 73 } |
74 | 74 |
75 void OmniboxPopupViewMac::UpdatePopupAppearance() { | 75 void OmniboxPopupViewMac::UpdatePopupAppearance() { |
76 DCHECK([NSThread isMainThread]); | 76 DCHECK([NSThread isMainThread]); |
77 const AutocompleteResult& result = GetResult(); | 77 const AutocompleteResult& result = GetResult(); |
78 const size_t start_match = result.ShouldHideTopMatch() ? 1 : 0; | 78 const size_t start_match = result.ShouldHideTopMatch() ? 1 : 0; |
79 const size_t rows = result.size() - start_match; | 79 const size_t rows = result.size() - start_match; |
80 if (rows == 0) { | 80 if (rows == 0) { |
81 [[popup_ parentWindow] removeChildWindow:popup_]; | 81 [[popup_ parentWindow] removeChildWindow:popup_]; |
82 [popup_ orderOut:nil]; | 82 [popup_ orderOut:nil]; |
83 | 83 |
84 // Break references to |this| because the popup may not be | 84 // Break references to |this| because the popup may not be |
85 // deallocated immediately. | 85 // deallocated immediately. |
86 [matrix_ setDelegate:nil]; | 86 [matrix_ setTheDelegate:NULL]; |
87 matrix_.reset(); | 87 matrix_.reset(); |
88 | 88 |
89 popup_.reset(nil); | 89 popup_.reset(nil); |
90 | 90 |
91 target_popup_frame_ = NSZeroRect; | 91 target_popup_frame_ = NSZeroRect; |
92 | 92 |
93 return; | 93 return; |
94 } | 94 } |
95 | 95 |
96 CreatePopupIfNeeded(); | 96 CreatePopupIfNeeded(); |
97 | 97 |
98 // Calculate the width of the matrix based on backing out the popup's border | |
99 // from the width of the field. | |
100 const CGFloat matrix_width = NSWidth([field_ bounds]); | |
101 DCHECK_GT(matrix_width, 0.0); | |
102 | |
103 // Load the results into the popup's matrix. | 98 // Load the results into the popup's matrix. |
104 DCHECK_GT(rows, 0U); | 99 DCHECK_GT(rows, 0U); |
105 [matrix_ renewRows:rows columns:1]; | 100 NSMutableArray* array = [NSMutableArray array]; |
106 CGFloat max_match_contents_width = 0.0f; | 101 NSInteger popupHeight = 0; |
107 CGFloat contents_offset = -1.0f; | |
108 for (size_t ii = 0; ii < rows; ++ii) { | 102 for (size_t ii = 0; ii < rows; ++ii) { |
109 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; | |
110 const AutocompleteMatch& match = GetResult().match_at(ii + start_match); | 103 const AutocompleteMatch& match = GetResult().match_at(ii + start_match); |
111 [cell setImage:ImageForMatch(match)]; | 104 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; |
112 [cell setMatch:match]; | 105 AutocompleteMatchWrapper* acm = |
113 if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) { | 106 [[AutocompleteMatchWrapper alloc] autorelease]; |
Scott Hess - ex-Googler
2015/05/04 19:40:21
-init in here, too.
dschuyler
2015/05/04 23:51:41
Done.
| |
114 max_match_contents_width = std::max(max_match_contents_width, | 107 acm->match_ = match; |
115 [cell getMatchContentsWidth]); | 108 [dictionary setObject:acm forKey:@"match"]; |
116 if (contents_offset < 0.0f) { | 109 NSImage* image = ImageForMatch(match); |
117 contents_offset = [OmniboxPopupCell computeContentsOffset:match]; | 110 [dictionary setObject:image forKey:@"image"]; |
118 } | 111 CGFloat height = [image size].height + kCellHeightAdjust; |
119 [cell setContentsOffset:contents_offset]; | 112 [dictionary setObject:[NSNumber numberWithFloat:height] forKey:@"height"]; |
120 } | 113 [array addObject:dictionary]; |
114 popupHeight += height; | |
121 } | 115 } |
122 | 116 [matrix_ setDataArray:array]; |
123 for (size_t ii = 0; ii < rows; ++ii) { | 117 [matrix_ reloadData]; |
124 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; | 118 if (rows) |
125 [cell setMaxMatchContentsWidth:max_match_contents_width]; | 119 popupHeight += [matrix_ intercellSpacing].height * (rows - 1); |
126 } | |
127 | |
128 // Set the cell size to fit a line of text in the cell's font. All | |
129 // cells should use the same font and each should layout in one | |
130 // line, so they should all be about the same height. | |
131 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize]; | |
132 DCHECK_GT(cell_size.height, 0.0); | |
133 const CGFloat cell_height = cell_size.height + kCellHeightAdjust; | |
134 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)]; | |
135 | 120 |
136 // Update the selection before placing (and displaying) the window. | 121 // Update the selection before placing (and displaying) the window. |
137 PaintUpdatesNow(); | 122 PaintUpdatesNow(); |
138 | 123 |
139 // Calculate the matrix size manually rather than using -sizeToCells | 124 // Calculate the matrix size manually rather than using -sizeToCells |
140 // because actually resizing the matrix messed up the popup size | 125 // because actually resizing the matrix messed up the popup size |
141 // animation. | 126 // animation. |
142 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); | 127 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); |
143 PositionPopup(rows * cell_height); | 128 PositionPopup(popupHeight); |
144 } | 129 } |
145 | 130 |
146 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { | 131 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { |
147 // Flip the coordinate system before returning. | 132 // Flip the coordinate system before returning. |
148 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; | 133 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; |
149 NSRect monitor_frame = [screen frame]; | 134 NSRect monitor_frame = [screen frame]; |
150 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); | 135 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); |
151 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); | 136 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); |
152 return bounds; | 137 return bounds; |
153 } | 138 } |
154 | 139 |
155 // This is only called by model in SetSelectedLine() after updating | 140 // This is only called by model in SetSelectedLine() after updating |
156 // everything. Popup should already be visible. | 141 // everything. Popup should already be visible. |
157 void OmniboxPopupViewMac::PaintUpdatesNow() { | 142 void OmniboxPopupViewMac::PaintUpdatesNow() { |
158 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 143 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
159 if (start_match > model_->selected_line()) { | 144 NSIndexSet* indexSet = [NSIndexSet indexSet]; |
160 [matrix_ deselectAllCells]; | 145 if (start_match <= model_->selected_line()) { |
161 } else { | 146 indexSet = |
162 [matrix_ selectCellAtRow:model_->selected_line() - start_match column:0]; | 147 [NSIndexSet indexSetWithIndex:model_->selected_line() - start_match]; |
163 } | 148 } |
164 | 149 [matrix_ selectRowIndexes:indexSet byExtendingSelection:NO]; |
165 } | 150 } |
166 | 151 |
167 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, | 152 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, |
168 size_t row) { | 153 size_t row) { |
169 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 154 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
170 model_->SetSelectedLine(row + start_match, false, false); | 155 model_->SetSelectedLine(row + start_match, false, false); |
171 } | 156 } |
172 | 157 |
173 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, | 158 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, |
174 size_t row) { | 159 size_t row) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
235 NSRect popup_frame = anchor_rect_base; | 220 NSRect popup_frame = anchor_rect_base; |
236 // Size to fit the matrix and shift down by the size. | 221 // Size to fit the matrix and shift down by the size. |
237 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; | 222 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; |
238 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; | 223 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; |
239 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; | 224 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; |
240 popup_frame.origin.y -= NSHeight(popup_frame); | 225 popup_frame.origin.y -= NSHeight(popup_frame); |
241 // Shift to screen coordinates. | 226 // Shift to screen coordinates. |
242 popup_frame.origin = | 227 popup_frame.origin = |
243 [[controller window] convertBaseToScreen:popup_frame.origin]; | 228 [[controller window] convertBaseToScreen:popup_frame.origin]; |
244 | 229 |
245 // Do nothing if the popup is already animating to the given |frame|. | |
246 if (NSEqualRects(popup_frame, target_popup_frame_)) | |
247 return; | |
248 | |
249 // Top separator. | 230 // Top separator. |
250 NSRect top_separator_frame = NSZeroRect; | 231 NSRect top_separator_frame = NSZeroRect; |
251 top_separator_frame.size.width = NSWidth(popup_frame); | 232 top_separator_frame.size.width = NSWidth(popup_frame); |
252 top_separator_frame.size.height = | 233 top_separator_frame.size.height = |
253 [OmniboxPopupTopSeparatorView preferredHeight]; | 234 [OmniboxPopupTopSeparatorView preferredHeight]; |
254 [top_separator_view_ setFrame:top_separator_frame]; | 235 [top_separator_view_ setFrame:top_separator_frame]; |
255 | 236 |
256 // Bottom separator. | 237 // Bottom separator. |
257 NSRect bottom_separator_frame = NSZeroRect; | 238 NSRect bottom_separator_frame = NSZeroRect; |
258 bottom_separator_frame.size.width = NSWidth(popup_frame); | 239 bottom_separator_frame.size.width = NSWidth(popup_frame); |
259 bottom_separator_frame.size.height = | 240 bottom_separator_frame.size.height = |
260 [OmniboxPopupBottomSeparatorView preferredHeight]; | 241 [OmniboxPopupBottomSeparatorView preferredHeight]; |
261 bottom_separator_frame.origin.y = | 242 bottom_separator_frame.origin.y = |
262 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); | 243 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); |
263 [bottom_separator_view_ setFrame:bottom_separator_frame]; | 244 [bottom_separator_view_ setFrame:bottom_separator_frame]; |
264 | 245 |
265 // Background view. | 246 // Background view. |
266 NSRect background_rect = NSZeroRect; | 247 NSRect background_rect = NSZeroRect; |
267 background_rect.size.width = NSWidth(popup_frame); | 248 background_rect.size.width = NSWidth(popup_frame); |
268 background_rect.size.height = NSHeight(popup_frame) - | 249 background_rect.size.height = NSHeight(popup_frame) - |
269 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); | 250 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); |
270 background_rect.origin.y = NSMaxY(top_separator_frame); | 251 background_rect.origin.y = NSMaxY(top_separator_frame); |
271 [background_view_ setFrame:background_rect]; | 252 [background_view_ setFrame:background_rect]; |
272 | 253 |
254 // Calculate the width of the table based on backing out the popup's border | |
255 // from the width of the field. | |
256 const CGFloat tableWidth = NSWidth([field_ bounds]); | |
257 DCHECK_GT(tableWidth, 0.0); | |
258 | |
273 // Matrix. | 259 // Matrix. |
274 NSPoint field_origin_base = | 260 NSPoint field_origin_base = |
275 [field_ convertPoint:[field_ bounds].origin toView:nil]; | 261 [field_ convertPoint:[field_ bounds].origin toView:nil]; |
276 NSRect matrix_frame = NSZeroRect; | 262 NSRect matrix_frame = NSZeroRect; |
277 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); | 263 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); |
278 matrix_frame.origin.y = kPopupPaddingVertical; | 264 matrix_frame.origin.y = kPopupPaddingVertical; |
279 matrix_frame.size.width = [matrix_ cellSize].width; | 265 matrix_frame.size.width = tableWidth; |
280 matrix_frame.size.height = matrixHeight; | 266 matrix_frame.size.height = matrixHeight; |
281 [matrix_ setFrame:matrix_frame]; | 267 [matrix_ setFrame:matrix_frame]; |
282 | 268 |
283 NSRect current_poup_frame = [popup_ frame]; | 269 NSRect current_poup_frame = [popup_ frame]; |
284 target_popup_frame_ = popup_frame; | 270 target_popup_frame_ = popup_frame; |
285 | 271 |
286 // Animate the frame change if the only change is that the height got smaller. | 272 // Animate the frame change if the only change is that the height got smaller. |
287 // Otherwise, resize immediately. | 273 // Otherwise, resize immediately. |
288 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && | 274 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && |
289 NSWidth(popup_frame) == NSWidth(current_poup_frame)); | 275 NSWidth(popup_frame) == NSWidth(current_poup_frame)); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
329 } | 315 } |
330 | 316 |
331 void OmniboxPopupViewMac::OpenURLForRow(size_t row, | 317 void OmniboxPopupViewMac::OpenURLForRow(size_t row, |
332 WindowOpenDisposition disposition) { | 318 WindowOpenDisposition disposition) { |
333 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 319 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
334 row += start_match; | 320 row += start_match; |
335 DCHECK_LT(row, GetResult().size()); | 321 DCHECK_LT(row, GetResult().size()); |
336 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), | 322 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), |
337 base::string16(), row); | 323 base::string16(), row); |
338 } | 324 } |
OLD | NEW |