Chromium Code Reviews| 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; |
|
Scott Hess - ex-Googler
2015/05/07 22:35:42
CGFloat.
dschuyler
2015/05/13 01:41:11
Done.
| |
| 107 CGFloat contents_offset = -1.0f; | 102 NSRect cellRect = NSZeroRect; |
| 103 cellRect.size.width = NSWidth([field_ bounds]); | |
|
Scott Hess - ex-Googler
2015/05/07 22:35:42
Actually, just set it to [field_ bounds], so that
| |
| 108 for (size_t ii = 0; ii < rows; ++ii) { | 104 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); | 105 const AutocompleteMatch& match = GetResult().match_at(ii + start_match); |
| 111 [cell setImage:ImageForMatch(match)]; | 106 NSMutableDictionary* dictionary = [NSMutableDictionary dictionary]; |
| 112 [cell setMatch:match]; | 107 AutocompleteMatchWrapper* acm = |
| 113 if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) { | 108 [[[AutocompleteMatchWrapper alloc] init] autorelease]; |
| 114 max_match_contents_width = std::max(max_match_contents_width, | 109 acm->match_ = match; |
|
Scott Hess - ex-Googler
2015/05/07 22:35:42
Starting to wonder if you shouldn't rather impleme
dschuyler
2015/05/13 01:41:11
Yeah, that makes sense. The wrapper class is gone
| |
| 115 [cell getMatchContentsWidth]); | 110 [dictionary setObject:acm forKey:@"match"]; |
| 116 if (contents_offset < 0.0f) { | 111 NSImage* image = ImageForMatch(match); |
| 117 contents_offset = [OmniboxPopupCell computeContentsOffset:match]; | 112 [dictionary setObject:image forKey:@"image"]; |
| 118 } | 113 cellRect.origin.y = popupHeight; |
| 119 [cell setContentsOffset:contents_offset]; | 114 CGFloat height = [image size].height + kCellHeightAdjust; |
| 120 } | 115 cellRect.size.height = height; |
| 116 [dictionary setObject:[NSValue valueWithRect:cellRect] forKey:@"rect"]; | |
| 117 [array addObject:dictionary]; | |
| 118 popupHeight += height; | |
|
Scott Hess - ex-Googler
2015/05/07 22:35:42
I'd set cellRect.size.height directly, then use NS
dschuyler
2015/05/13 01:41:11
I used cellRect.size.height because for readabilit
| |
| 121 } | 119 } |
| 122 | 120 [matrix_ setDataArray:array]; |
| 123 for (size_t ii = 0; ii < rows; ++ii) { | 121 [matrix_ reloadData]; |
| 124 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; | 122 if (rows) |
| 125 [cell setMaxMatchContentsWidth:max_match_contents_width]; | 123 popupHeight += [matrix_ intercellSpacing].height * (rows - 1); |
|
Scott Hess - ex-Googler
2015/05/07 22:35:42
WDYT of having the entire loop in this if()?
That
groby-ooo-7-16
2015/05/08 03:24:08
+1 on "don't bother". Either we assert rows is *al
dschuyler
2015/05/13 01:41:11
I went with the DCHECK_GT option :)
| |
| 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 | 124 |
| 136 // Update the selection before placing (and displaying) the window. | 125 // Update the selection before placing (and displaying) the window. |
| 137 PaintUpdatesNow(); | 126 PaintUpdatesNow(); |
| 138 | 127 |
| 139 // Calculate the matrix size manually rather than using -sizeToCells | 128 // Calculate the matrix size manually rather than using -sizeToCells |
| 140 // because actually resizing the matrix messed up the popup size | 129 // because actually resizing the matrix messed up the popup size |
| 141 // animation. | 130 // animation. |
| 142 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); | 131 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); |
| 143 PositionPopup(rows * cell_height); | 132 PositionPopup(popupHeight); |
| 144 } | 133 } |
| 145 | 134 |
| 146 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { | 135 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { |
| 147 // Flip the coordinate system before returning. | 136 // Flip the coordinate system before returning. |
| 148 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; | 137 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; |
| 149 NSRect monitor_frame = [screen frame]; | 138 NSRect monitor_frame = [screen frame]; |
| 150 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); | 139 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); |
| 151 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); | 140 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); |
| 152 return bounds; | 141 return bounds; |
| 153 } | 142 } |
| 154 | 143 |
| 155 // This is only called by model in SetSelectedLine() after updating | 144 // This is only called by model in SetSelectedLine() after updating |
| 156 // everything. Popup should already be visible. | 145 // everything. Popup should already be visible. |
| 157 void OmniboxPopupViewMac::PaintUpdatesNow() { | 146 void OmniboxPopupViewMac::PaintUpdatesNow() { |
| 158 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 147 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
| 159 if (start_match > model_->selected_line()) { | 148 NSIndexSet* indexSet = [NSIndexSet indexSet]; |
| 160 [matrix_ deselectAllCells]; | 149 if (start_match <= model_->selected_line()) { |
| 161 } else { | 150 indexSet = |
| 162 [matrix_ selectCellAtRow:model_->selected_line() - start_match column:0]; | 151 [NSIndexSet indexSetWithIndex:model_->selected_line() - start_match]; |
| 163 } | 152 } |
| 164 | 153 [matrix_ selectRowIndexes:indexSet byExtendingSelection:NO]; |
| 165 } | 154 } |
| 166 | 155 |
| 167 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, | 156 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, |
| 168 size_t row) { | 157 size_t row) { |
| 169 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 158 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
| 170 model_->SetSelectedLine(row + start_match, false, false); | 159 model_->SetSelectedLine(row + start_match, false, false); |
| 171 } | 160 } |
| 172 | 161 |
| 173 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, | 162 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, |
| 174 size_t row) { | 163 size_t row) { |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 235 NSRect popup_frame = anchor_rect_base; | 224 NSRect popup_frame = anchor_rect_base; |
| 236 // Size to fit the matrix and shift down by the size. | 225 // Size to fit the matrix and shift down by the size. |
| 237 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; | 226 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; |
| 238 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; | 227 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; |
| 239 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; | 228 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; |
| 240 popup_frame.origin.y -= NSHeight(popup_frame); | 229 popup_frame.origin.y -= NSHeight(popup_frame); |
| 241 // Shift to screen coordinates. | 230 // Shift to screen coordinates. |
| 242 popup_frame.origin = | 231 popup_frame.origin = |
| 243 [[controller window] convertBaseToScreen:popup_frame.origin]; | 232 [[controller window] convertBaseToScreen:popup_frame.origin]; |
| 244 | 233 |
| 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. | 234 // Top separator. |
| 250 NSRect top_separator_frame = NSZeroRect; | 235 NSRect top_separator_frame = NSZeroRect; |
| 251 top_separator_frame.size.width = NSWidth(popup_frame); | 236 top_separator_frame.size.width = NSWidth(popup_frame); |
| 252 top_separator_frame.size.height = | 237 top_separator_frame.size.height = |
| 253 [OmniboxPopupTopSeparatorView preferredHeight]; | 238 [OmniboxPopupTopSeparatorView preferredHeight]; |
| 254 [top_separator_view_ setFrame:top_separator_frame]; | 239 [top_separator_view_ setFrame:top_separator_frame]; |
| 255 | 240 |
| 256 // Bottom separator. | 241 // Bottom separator. |
| 257 NSRect bottom_separator_frame = NSZeroRect; | 242 NSRect bottom_separator_frame = NSZeroRect; |
| 258 bottom_separator_frame.size.width = NSWidth(popup_frame); | 243 bottom_separator_frame.size.width = NSWidth(popup_frame); |
| 259 bottom_separator_frame.size.height = | 244 bottom_separator_frame.size.height = |
| 260 [OmniboxPopupBottomSeparatorView preferredHeight]; | 245 [OmniboxPopupBottomSeparatorView preferredHeight]; |
| 261 bottom_separator_frame.origin.y = | 246 bottom_separator_frame.origin.y = |
| 262 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); | 247 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); |
| 263 [bottom_separator_view_ setFrame:bottom_separator_frame]; | 248 [bottom_separator_view_ setFrame:bottom_separator_frame]; |
| 264 | 249 |
| 265 // Background view. | 250 // Background view. |
| 266 NSRect background_rect = NSZeroRect; | 251 NSRect background_rect = NSZeroRect; |
| 267 background_rect.size.width = NSWidth(popup_frame); | 252 background_rect.size.width = NSWidth(popup_frame); |
| 268 background_rect.size.height = NSHeight(popup_frame) - | 253 background_rect.size.height = NSHeight(popup_frame) - |
| 269 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); | 254 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); |
| 270 background_rect.origin.y = NSMaxY(top_separator_frame); | 255 background_rect.origin.y = NSMaxY(top_separator_frame); |
| 271 [background_view_ setFrame:background_rect]; | 256 [background_view_ setFrame:background_rect]; |
| 272 | 257 |
| 258 // Calculate the width of the table based on backing out the popup's border | |
| 259 // from the width of the field. | |
| 260 const CGFloat tableWidth = NSWidth([field_ bounds]); | |
| 261 DCHECK_GT(tableWidth, 0.0); | |
| 262 | |
| 273 // Matrix. | 263 // Matrix. |
| 274 NSPoint field_origin_base = | 264 NSPoint field_origin_base = |
| 275 [field_ convertPoint:[field_ bounds].origin toView:nil]; | 265 [field_ convertPoint:[field_ bounds].origin toView:nil]; |
| 276 NSRect matrix_frame = NSZeroRect; | 266 NSRect matrix_frame = NSZeroRect; |
| 277 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); | 267 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); |
| 278 matrix_frame.origin.y = kPopupPaddingVertical; | 268 matrix_frame.origin.y = kPopupPaddingVertical; |
| 279 matrix_frame.size.width = [matrix_ cellSize].width; | 269 matrix_frame.size.width = tableWidth; |
| 280 matrix_frame.size.height = matrixHeight; | 270 matrix_frame.size.height = matrixHeight; |
| 281 [matrix_ setFrame:matrix_frame]; | 271 [matrix_ setFrame:matrix_frame]; |
| 282 | 272 |
| 283 NSRect current_poup_frame = [popup_ frame]; | 273 NSRect current_poup_frame = [popup_ frame]; |
| 284 target_popup_frame_ = popup_frame; | 274 target_popup_frame_ = popup_frame; |
| 285 | 275 |
| 286 // Animate the frame change if the only change is that the height got smaller. | 276 // Animate the frame change if the only change is that the height got smaller. |
| 287 // Otherwise, resize immediately. | 277 // Otherwise, resize immediately. |
| 288 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && | 278 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && |
| 289 NSWidth(popup_frame) == NSWidth(current_poup_frame)); | 279 NSWidth(popup_frame) == NSWidth(current_poup_frame)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 } | 319 } |
| 330 | 320 |
| 331 void OmniboxPopupViewMac::OpenURLForRow(size_t row, | 321 void OmniboxPopupViewMac::OpenURLForRow(size_t row, |
| 332 WindowOpenDisposition disposition) { | 322 WindowOpenDisposition disposition) { |
| 333 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; | 323 size_t start_match = model_->result().ShouldHideTopMatch() ? 1 : 0; |
| 334 row += start_match; | 324 row += start_match; |
| 335 DCHECK_LT(row, GetResult().size()); | 325 DCHECK_LT(row, GetResult().size()); |
| 336 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), | 326 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), |
| 337 base::string16(), row); | 327 base::string16(), row); |
| 338 } | 328 } |
| OLD | NEW |