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 11 matching lines...) Expand all Loading... |
22 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" | 22 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h
" |
23 #import "ui/base/cocoa/cocoa_base_utils.h" | 23 #import "ui/base/cocoa/cocoa_base_utils.h" |
24 #import "ui/base/cocoa/flipped_view.h" | 24 #import "ui/base/cocoa/flipped_view.h" |
25 #include "ui/base/cocoa/window_size_constants.h" | 25 #include "ui/base/cocoa/window_size_constants.h" |
26 #include "ui/gfx/geometry/rect.h" | 26 #include "ui/gfx/geometry/rect.h" |
27 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 27 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
28 #include "ui/gfx/text_elider.h" | 28 #include "ui/gfx/text_elider.h" |
29 | 29 |
30 namespace { | 30 namespace { |
31 | 31 |
32 // How much to adjust the cell sizing up from the default determined | |
33 // by the font. | |
34 const CGFloat kCellHeightAdjust = 6.0; | |
35 | |
36 // Padding between matrix and the top and bottom of the popup window. | 32 // Padding between matrix and the top and bottom of the popup window. |
37 const CGFloat kPopupPaddingVertical = 5.0; | 33 const CGFloat kPopupPaddingVertical = 5.0; |
38 | 34 |
39 // Animation duration when animating the popup window smaller. | 35 // Animation duration when animating the popup window smaller. |
40 const NSTimeInterval kShrinkAnimationDuration = 0.1; | 36 const NSTimeInterval kShrinkAnimationDuration = 0.1; |
41 | 37 |
42 // Background colors for different states of the popup elements. | 38 // Background colors for different states of the popup elements. |
43 NSColor* BackgroundColor() { | 39 NSColor* BackgroundColor() { |
44 return [NSColor controlBackgroundColor]; | 40 return [NSColor controlBackgroundColor]; |
45 } | 41 } |
(...skipping 29 matching lines...) Expand all Loading... |
75 void OmniboxPopupViewMac::UpdatePopupAppearance() { | 71 void OmniboxPopupViewMac::UpdatePopupAppearance() { |
76 DCHECK([NSThread isMainThread]); | 72 DCHECK([NSThread isMainThread]); |
77 const AutocompleteResult& result = GetResult(); | 73 const AutocompleteResult& result = GetResult(); |
78 const size_t rows = result.size(); | 74 const size_t rows = result.size(); |
79 if (rows == 0) { | 75 if (rows == 0) { |
80 [[popup_ parentWindow] removeChildWindow:popup_]; | 76 [[popup_ parentWindow] removeChildWindow:popup_]; |
81 [popup_ orderOut:nil]; | 77 [popup_ orderOut:nil]; |
82 | 78 |
83 // Break references to |this| because the popup may not be | 79 // Break references to |this| because the popup may not be |
84 // deallocated immediately. | 80 // deallocated immediately. |
85 [matrix_ setDelegate:nil]; | 81 [matrix_ setObserver:NULL]; |
86 matrix_.reset(); | 82 matrix_.reset(); |
87 | 83 |
88 popup_.reset(nil); | 84 popup_.reset(nil); |
89 | 85 |
90 target_popup_frame_ = NSZeroRect; | 86 target_popup_frame_ = NSZeroRect; |
91 | 87 |
92 return; | 88 return; |
93 } | 89 } |
94 | 90 |
95 CreatePopupIfNeeded(); | 91 CreatePopupIfNeeded(); |
96 | 92 |
97 // Calculate the width of the matrix based on backing out the popup's border | 93 NSImage* answerImage = nil; |
98 // from the width of the field. | 94 if (!model_->answer_bitmap().isNull()) { |
99 const CGFloat matrix_width = NSWidth([field_ bounds]); | 95 answerImage = |
100 DCHECK_GT(matrix_width, 0.0); | 96 gfx::Image::CreateFrom1xBitmap(model_->answer_bitmap()).CopyNSImage(); |
101 | |
102 // Load the results into the popup's matrix. | |
103 DCHECK_GT(rows, 0U); | |
104 [matrix_ renewRows:rows columns:1]; | |
105 CGFloat max_match_contents_width = 0.0f; | |
106 CGFloat contents_offset = -1.0f; | |
107 for (size_t ii = 0; ii < rows; ++ii) { | |
108 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; | |
109 const AutocompleteMatch& match = GetResult().match_at(ii); | |
110 [cell setImage:ImageForMatch(match)]; | |
111 [cell setMatch:match]; | |
112 // Only set the image on the one cell with match.answer. | |
113 if (match.answer && !model_->answer_bitmap().isNull()) { | |
114 NSImage* image = | |
115 gfx::Image::CreateFrom1xBitmap(model_->answer_bitmap()).CopyNSImage(); | |
116 [cell setAnswerImage:image]; | |
117 } | |
118 if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_TAIL) { | |
119 max_match_contents_width = std::max(max_match_contents_width, | |
120 [cell getMatchContentsWidth]); | |
121 if (contents_offset < 0.0f) { | |
122 contents_offset = [OmniboxPopupCell computeContentsOffset:match]; | |
123 } | |
124 [cell setContentsOffset:contents_offset]; | |
125 } | |
126 } | 97 } |
127 | 98 [matrix_ setController:[[OmniboxPopupTableController alloc] |
128 for (size_t ii = 0; ii < rows; ++ii) { | 99 initWithMatchResults:result |
129 OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0]; | 100 tableView:matrix_ |
130 [cell setMaxMatchContentsWidth:max_match_contents_width]; | 101 popupView:*this |
131 } | 102 answerImage:answerImage]]; |
132 | 103 [matrix_ setSeparator:[OmniboxPopupCell createSeparatorString]]; |
133 // Set the cell size to fit a line of text in the cell's font. All | |
134 // cells should use the same font and each should layout in one | |
135 // line, so they should all be about the same height. | |
136 const NSSize cell_size = [[matrix_ cellAtRow:0 column:0] cellSize]; | |
137 DCHECK_GT(cell_size.height, 0.0); | |
138 const CGFloat cell_height = cell_size.height + kCellHeightAdjust; | |
139 [matrix_ setCellSize:NSMakeSize(matrix_width, cell_height)]; | |
140 | 104 |
141 // Update the selection before placing (and displaying) the window. | 105 // Update the selection before placing (and displaying) the window. |
142 PaintUpdatesNow(); | 106 PaintUpdatesNow(); |
143 | 107 |
144 // Calculate the matrix size manually rather than using -sizeToCells | 108 // Calculate the matrix size manually rather than using -sizeToCells |
145 // because actually resizing the matrix messed up the popup size | 109 // because actually resizing the matrix messed up the popup size |
146 // animation. | 110 // animation. |
147 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); | 111 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); |
148 PositionPopup(rows * cell_height); | 112 PositionPopup(NSHeight([matrix_ frame])); |
149 } | 113 } |
150 | 114 |
151 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { | 115 gfx::Rect OmniboxPopupViewMac::GetTargetBounds() { |
152 // Flip the coordinate system before returning. | 116 // Flip the coordinate system before returning. |
153 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; | 117 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; |
154 NSRect monitor_frame = [screen frame]; | 118 NSRect monitor_frame = [screen frame]; |
155 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); | 119 gfx::Rect bounds(NSRectToCGRect(target_popup_frame_)); |
156 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); | 120 bounds.set_y(monitor_frame.size.height - bounds.y() - bounds.height()); |
157 return bounds; | 121 return bounds; |
158 } | 122 } |
159 | 123 |
160 // This is only called by model in SetSelectedLine() after updating | 124 // This is only called by model in SetSelectedLine() after updating |
161 // everything. Popup should already be visible. | 125 // everything. Popup should already be visible. |
162 void OmniboxPopupViewMac::PaintUpdatesNow() { | 126 void OmniboxPopupViewMac::PaintUpdatesNow() { |
163 [matrix_ selectCellAtRow:model_->selected_line() column:0]; | 127 [matrix_ selectRowIndex:model_->selected_line()]; |
164 } | 128 } |
165 | 129 |
166 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, | 130 void OmniboxPopupViewMac::OnMatrixRowSelected(OmniboxPopupMatrix* matrix, |
167 size_t row) { | 131 size_t row) { |
168 model_->SetSelectedLine(row, false, false); | 132 model_->SetSelectedLine(row, false, false); |
169 } | 133 } |
170 | 134 |
171 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, | 135 void OmniboxPopupViewMac::OnMatrixRowClicked(OmniboxPopupMatrix* matrix, |
172 size_t row) { | 136 size_t row) { |
173 OpenURLForRow(row, | 137 OpenURLForRow(row, |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 NSRect popup_frame = anchor_rect_base; | 197 NSRect popup_frame = anchor_rect_base; |
234 // Size to fit the matrix and shift down by the size. | 198 // Size to fit the matrix and shift down by the size. |
235 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; | 199 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; |
236 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; | 200 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; |
237 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; | 201 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; |
238 popup_frame.origin.y -= NSHeight(popup_frame); | 202 popup_frame.origin.y -= NSHeight(popup_frame); |
239 // Shift to screen coordinates. | 203 // Shift to screen coordinates. |
240 popup_frame.origin = | 204 popup_frame.origin = |
241 [[controller window] convertBaseToScreen:popup_frame.origin]; | 205 [[controller window] convertBaseToScreen:popup_frame.origin]; |
242 | 206 |
243 // Do nothing if the popup is already animating to the given |frame|. | |
244 if (NSEqualRects(popup_frame, target_popup_frame_)) | |
245 return; | |
246 | |
247 // Top separator. | 207 // Top separator. |
248 NSRect top_separator_frame = NSZeroRect; | 208 NSRect top_separator_frame = NSZeroRect; |
249 top_separator_frame.size.width = NSWidth(popup_frame); | 209 top_separator_frame.size.width = NSWidth(popup_frame); |
250 top_separator_frame.size.height = | 210 top_separator_frame.size.height = |
251 [OmniboxPopupTopSeparatorView preferredHeight]; | 211 [OmniboxPopupTopSeparatorView preferredHeight]; |
252 [top_separator_view_ setFrame:top_separator_frame]; | 212 [top_separator_view_ setFrame:top_separator_frame]; |
253 | 213 |
254 // Bottom separator. | 214 // Bottom separator. |
255 NSRect bottom_separator_frame = NSZeroRect; | 215 NSRect bottom_separator_frame = NSZeroRect; |
256 bottom_separator_frame.size.width = NSWidth(popup_frame); | 216 bottom_separator_frame.size.width = NSWidth(popup_frame); |
257 bottom_separator_frame.size.height = | 217 bottom_separator_frame.size.height = |
258 [OmniboxPopupBottomSeparatorView preferredHeight]; | 218 [OmniboxPopupBottomSeparatorView preferredHeight]; |
259 bottom_separator_frame.origin.y = | 219 bottom_separator_frame.origin.y = |
260 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); | 220 NSHeight(popup_frame) - NSHeight(bottom_separator_frame); |
261 [bottom_separator_view_ setFrame:bottom_separator_frame]; | 221 [bottom_separator_view_ setFrame:bottom_separator_frame]; |
262 | 222 |
263 // Background view. | 223 // Background view. |
264 NSRect background_rect = NSZeroRect; | 224 NSRect background_rect = NSZeroRect; |
265 background_rect.size.width = NSWidth(popup_frame); | 225 background_rect.size.width = NSWidth(popup_frame); |
266 background_rect.size.height = NSHeight(popup_frame) - | 226 background_rect.size.height = NSHeight(popup_frame) - |
267 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); | 227 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); |
268 background_rect.origin.y = NSMaxY(top_separator_frame); | 228 background_rect.origin.y = NSMaxY(top_separator_frame); |
269 [background_view_ setFrame:background_rect]; | 229 [background_view_ setFrame:background_rect]; |
270 | 230 |
| 231 // Calculate the width of the table based on backing out the popup's border |
| 232 // from the width of the field. |
| 233 const CGFloat tableWidth = NSWidth([field_ bounds]); |
| 234 DCHECK_GT(tableWidth, 0.0); |
| 235 |
271 // Matrix. | 236 // Matrix. |
272 NSPoint field_origin_base = | 237 NSPoint field_origin_base = |
273 [field_ convertPoint:[field_ bounds].origin toView:nil]; | 238 [field_ convertPoint:[field_ bounds].origin toView:nil]; |
274 NSRect matrix_frame = NSZeroRect; | 239 NSRect matrix_frame = NSZeroRect; |
275 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); | 240 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); |
276 matrix_frame.origin.y = kPopupPaddingVertical; | 241 matrix_frame.origin.y = kPopupPaddingVertical; |
277 matrix_frame.size.width = [matrix_ cellSize].width; | 242 matrix_frame.size.width = tableWidth; |
278 matrix_frame.size.height = matrixHeight; | 243 matrix_frame.size.height = matrixHeight; |
279 [matrix_ setFrame:matrix_frame]; | 244 [matrix_ setFrame:matrix_frame]; |
280 | 245 |
281 NSRect current_poup_frame = [popup_ frame]; | 246 NSRect current_poup_frame = [popup_ frame]; |
282 target_popup_frame_ = popup_frame; | 247 target_popup_frame_ = popup_frame; |
283 | 248 |
284 // Animate the frame change if the only change is that the height got smaller. | 249 // Animate the frame change if the only change is that the height got smaller. |
285 // Otherwise, resize immediately. | 250 // Otherwise, resize immediately. |
286 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && | 251 bool animate = (NSHeight(popup_frame) < NSHeight(current_poup_frame) && |
287 NSWidth(popup_frame) == NSWidth(current_poup_frame)); | 252 NSWidth(popup_frame) == NSWidth(current_poup_frame)); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); | 291 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); |
327 return OmniboxViewMac::ImageForResource(resource_id); | 292 return OmniboxViewMac::ImageForResource(resource_id); |
328 } | 293 } |
329 | 294 |
330 void OmniboxPopupViewMac::OpenURLForRow(size_t row, | 295 void OmniboxPopupViewMac::OpenURLForRow(size_t row, |
331 WindowOpenDisposition disposition) { | 296 WindowOpenDisposition disposition) { |
332 DCHECK_LT(row, GetResult().size()); | 297 DCHECK_LT(row, GetResult().size()); |
333 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), | 298 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), |
334 base::string16(), row); | 299 base::string16(), row); |
335 } | 300 } |
OLD | NEW |