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/mac/mac_util.h" | 9 #include "base/mac/mac_util.h" |
| 10 #import "base/mac/sdk_forward_declarations.h" | 10 #import "base/mac/sdk_forward_declarations.h" |
| 11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
| 12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
| 13 #include "chrome/browser/search/search.h" | 13 #include "chrome/browser/search/search.h" |
| 14 #include "chrome/browser/ui/cocoa/browser_window_controller.h" | 14 #include "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 15 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" | 15 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h" |
| 16 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h" | 16 #import "chrome/browser/ui/cocoa/omnibox/omnibox_popup_separator_view.h" |
| 17 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" | 17 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h" |
| 18 #include "components/omnibox/browser/autocomplete_match.h" | 18 #include "components/omnibox/browser/autocomplete_match.h" |
| 19 #include "components/omnibox/browser/autocomplete_match_type.h" | 19 #include "components/omnibox/browser/autocomplete_match_type.h" |
| 20 #include "components/omnibox/browser/omnibox_edit_model.h" | 20 #include "components/omnibox/browser/omnibox_edit_model.h" |
| 21 #include "components/omnibox/browser/omnibox_popup_model.h" | 21 #include "components/omnibox/browser/omnibox_popup_model.h" |
| 22 #include "grit/theme_resources.h" | 22 #include "grit/theme_resources.h" |
| 23 #include "skia/ext/skia_utils_mac.h" | 23 #include "skia/ext/skia_utils_mac.h" |
| 24 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h " | 24 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMNSAnimation+Duration.h " |
| 25 #import "ui/base/cocoa/cocoa_base_utils.h" | 25 #import "ui/base/cocoa/cocoa_base_utils.h" |
| 26 #import "ui/base/cocoa/flipped_view.h" | 26 #import "ui/base/cocoa/flipped_view.h" |
| 27 #include "ui/base/cocoa/window_size_constants.h" | 27 #include "ui/base/cocoa/window_size_constants.h" |
| 28 #include "ui/base/material_design/material_design_controller.h" | |
| 29 #include "ui/gfx/color_palette.h" | |
| 28 #include "ui/gfx/geometry/rect.h" | 30 #include "ui/gfx/geometry/rect.h" |
| 31 #include "ui/gfx/image/image_skia_util_mac.h" | |
| 32 #include "ui/gfx/paint_vector_icon.h" | |
| 29 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" | 33 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
| 30 #include "ui/gfx/text_elider.h" | 34 #include "ui/gfx/text_elider.h" |
| 35 #include "ui/gfx/vector_icons_public.h" | |
| 31 | 36 |
| 32 namespace { | 37 namespace { |
| 33 | 38 |
| 39 const int kPopupPaddingVertical = 5; | |
| 40 const int kMaterialPopupPaddingVertical = 4; | |
| 41 | |
| 34 // Padding between matrix and the top and bottom of the popup window. | 42 // Padding between matrix and the top and bottom of the popup window. |
| 35 const CGFloat kPopupPaddingVertical = 5.0; | 43 CGFloat PopupPaddingVertical() { |
| 44 if (!ui::MaterialDesignController::IsModeMaterial()) { | |
| 45 return kPopupPaddingVertical; | |
| 46 } | |
| 47 return kMaterialPopupPaddingVertical; | |
| 48 } | |
| 36 | 49 |
| 37 // Animation duration when animating the popup window smaller. | 50 // Animation duration when animating the popup window smaller. |
| 38 const NSTimeInterval kShrinkAnimationDuration = 0.1; | 51 const NSTimeInterval kShrinkAnimationDuration = 0.1; |
| 39 | 52 |
| 53 } // namespace | |
| 54 | |
| 40 // Background colors for different states of the popup elements. | 55 // Background colors for different states of the popup elements. |
| 41 NSColor* BackgroundColor() { | 56 // Static. |
|
tapted
2016/04/28 14:29:44
// static
(I guess this is one exception to the "
shrike
2016/04/28 21:05:35
Done.
| |
| 42 return [NSColor controlBackgroundColor]; | 57 |
|
tapted
2016/04/28 14:29:44
remove blank line
shrike
2016/04/28 21:05:35
Done.
| |
| 58 NSColor* OmniboxPopupViewMac::BackgroundColor(BOOL is_dark_theme) { | |
| 59 const CGFloat kMDDarkControlBackround = 40 / 255.; | |
| 60 return is_dark_theme | |
| 61 ? [NSColor colorWithGenericGamma22White:kMDDarkControlBackround alpha:1] | |
| 62 : [NSColor controlBackgroundColor]; | |
| 43 } | 63 } |
| 44 | 64 |
| 45 } // namespace | |
| 46 | |
| 47 OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view, | 65 OmniboxPopupViewMac::OmniboxPopupViewMac(OmniboxView* omnibox_view, |
| 48 OmniboxEditModel* edit_model, | 66 OmniboxEditModel* edit_model, |
| 49 NSTextField* field) | 67 NSTextField* field) |
| 50 : omnibox_view_(omnibox_view), | 68 : omnibox_view_(omnibox_view), |
| 51 model_(new OmniboxPopupModel(this, edit_model)), | 69 model_(new OmniboxPopupModel(this, edit_model)), |
| 52 field_(field), | 70 field_(field), |
| 53 popup_(nil), | 71 popup_(nil), |
| 54 target_popup_frame_(NSZeroRect) { | 72 target_popup_frame_(NSZeroRect) { |
| 55 DCHECK(omnibox_view); | 73 DCHECK(omnibox_view); |
| 56 DCHECK(edit_model); | 74 DCHECK(edit_model); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 NSImage* answerImage = nil; | 113 NSImage* answerImage = nil; |
| 96 if (!model_->answer_bitmap().isNull()) { | 114 if (!model_->answer_bitmap().isNull()) { |
| 97 answerImage = | 115 answerImage = |
| 98 gfx::Image::CreateFrom1xBitmap(model_->answer_bitmap()).CopyNSImage(); | 116 gfx::Image::CreateFrom1xBitmap(model_->answer_bitmap()).CopyNSImage(); |
| 99 } | 117 } |
| 100 [matrix_ setController:[[OmniboxPopupTableController alloc] | 118 [matrix_ setController:[[OmniboxPopupTableController alloc] |
| 101 initWithMatchResults:result | 119 initWithMatchResults:result |
| 102 tableView:matrix_ | 120 tableView:matrix_ |
| 103 popupView:*this | 121 popupView:*this |
| 104 answerImage:answerImage]]; | 122 answerImage:answerImage]]; |
| 105 [matrix_ setSeparator:[OmniboxPopupCell createSeparatorString]]; | 123 BOOL is_dark_theme = [matrix_ hasDarkTheme]; |
| 124 [matrix_ setSeparator: | |
| 125 [OmniboxPopupCell createSeparatorStringForDarkTheme:is_dark_theme]]; | |
| 106 | 126 |
| 107 // Update the selection before placing (and displaying) the window. | 127 // Update the selection before placing (and displaying) the window. |
| 108 PaintUpdatesNow(); | 128 PaintUpdatesNow(); |
| 109 | 129 |
| 110 // Calculate the matrix size manually rather than using -sizeToCells | 130 // Calculate the matrix size manually rather than using -sizeToCells |
| 111 // because actually resizing the matrix messed up the popup size | 131 // because actually resizing the matrix messed up the popup size |
| 112 // animation. | 132 // animation. |
| 113 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); | 133 DCHECK_EQ([matrix_ intercellSpacing].height, 0.0); |
| 114 PositionPopup(NSHeight([matrix_ frame])); | 134 PositionPopup(NSHeight([matrix_ frame])); |
| 115 } | 135 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 defer:NO]); | 178 defer:NO]); |
| 159 [popup_ setBackgroundColor:[NSColor clearColor]]; | 179 [popup_ setBackgroundColor:[NSColor clearColor]]; |
| 160 [popup_ setOpaque:NO]; | 180 [popup_ setOpaque:NO]; |
| 161 | 181 |
| 162 // Use a flipped view to pin the matrix top the top left. This is needed | 182 // Use a flipped view to pin the matrix top the top left. This is needed |
| 163 // for animated resize. | 183 // for animated resize. |
| 164 base::scoped_nsobject<FlippedView> contentView( | 184 base::scoped_nsobject<FlippedView> contentView( |
| 165 [[FlippedView alloc] initWithFrame:NSZeroRect]); | 185 [[FlippedView alloc] initWithFrame:NSZeroRect]); |
| 166 [popup_ setContentView:contentView]; | 186 [popup_ setContentView:contentView]; |
| 167 | 187 |
| 188 BOOL is_dark_theme = ui::MaterialDesignController::IsModeMaterial() && | |
| 189 [[field_ window] hasDarkTheme]; | |
| 190 | |
| 168 // View to draw a background beneath the matrix. | 191 // View to draw a background beneath the matrix. |
| 169 background_view_.reset([[NSBox alloc] initWithFrame:NSZeroRect]); | 192 background_view_.reset([[NSBox alloc] initWithFrame:NSZeroRect]); |
| 170 [background_view_ setBoxType:NSBoxCustom]; | 193 [background_view_ setBoxType:NSBoxCustom]; |
| 171 [background_view_ setBorderType:NSNoBorder]; | 194 [background_view_ setBorderType:NSNoBorder]; |
| 172 [background_view_ setFillColor:BackgroundColor()]; | 195 [background_view_ setFillColor:BackgroundColor(is_dark_theme)]; |
| 173 [background_view_ setContentViewMargins:NSZeroSize]; | 196 [background_view_ setContentViewMargins:NSZeroSize]; |
| 174 [contentView addSubview:background_view_]; | 197 [contentView addSubview:background_view_]; |
| 175 | 198 |
| 176 matrix_.reset([[OmniboxPopupMatrix alloc] initWithObserver:this]); | 199 matrix_.reset([[OmniboxPopupMatrix alloc] initWithObserver:this |
| 200 forDarkTheme:is_dark_theme]); | |
| 177 [background_view_ addSubview:matrix_]; | 201 [background_view_ addSubview:matrix_]; |
| 178 | 202 |
| 179 top_separator_view_.reset( | 203 top_separator_view_.reset( |
| 180 [[OmniboxPopupTopSeparatorView alloc] initWithFrame:NSZeroRect]); | 204 [[OmniboxPopupTopSeparatorView alloc] initWithFrame:NSZeroRect]); |
| 181 [contentView addSubview:top_separator_view_]; | 205 [contentView addSubview:top_separator_view_]; |
| 182 | 206 |
| 183 bottom_separator_view_.reset( | 207 bottom_separator_view_.reset( |
| 184 [[OmniboxPopupBottomSeparatorView alloc] initWithFrame:NSZeroRect]); | 208 [[OmniboxPopupBottomSeparatorView alloc] initWithFrame:NSZeroRect |
| 209 forDarkTheme:is_dark_theme]); | |
| 185 [contentView addSubview:bottom_separator_view_]; | 210 [contentView addSubview:bottom_separator_view_]; |
| 186 | 211 |
| 187 // TODO(dtseng): Ignore until we provide NSAccessibility support. | 212 // TODO(dtseng): Ignore until we provide NSAccessibility support. |
| 188 [popup_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole | 213 [popup_ accessibilitySetOverrideValue:NSAccessibilityUnknownRole |
| 189 forAttribute:NSAccessibilityRoleAttribute]; | 214 forAttribute:NSAccessibilityRoleAttribute]; |
| 190 } | 215 } |
| 191 } | 216 } |
| 192 | 217 |
| 193 void OmniboxPopupViewMac::PositionPopup(const CGFloat matrixHeight) { | 218 void OmniboxPopupViewMac::PositionPopup(const CGFloat matrixHeight) { |
| 194 BrowserWindowController* controller = | 219 BrowserWindowController* controller = |
| 195 [BrowserWindowController browserWindowControllerForView:field_]; | 220 [BrowserWindowController browserWindowControllerForView:field_]; |
| 196 NSRect anchor_rect_base = [controller omniboxPopupAnchorRect]; | 221 NSRect anchor_rect_base = [controller omniboxPopupAnchorRect]; |
| 197 | 222 |
| 198 // Calculate the popup's position on the screen. | 223 // Calculate the popup's position on the screen. |
| 199 NSRect popup_frame = anchor_rect_base; | 224 NSRect popup_frame = anchor_rect_base; |
| 200 // Size to fit the matrix and shift down by the size. | 225 // Size to fit the matrix and shift down by the size. |
| 201 popup_frame.size.height = matrixHeight + kPopupPaddingVertical * 2.0; | 226 popup_frame.size.height = matrixHeight + PopupPaddingVertical() * 2.0; |
| 202 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; | 227 popup_frame.size.height += [OmniboxPopupTopSeparatorView preferredHeight]; |
| 203 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; | 228 popup_frame.size.height += [OmniboxPopupBottomSeparatorView preferredHeight]; |
| 204 popup_frame.origin.y -= NSHeight(popup_frame); | 229 popup_frame.origin.y -= NSHeight(popup_frame); |
| 205 | 230 |
| 206 // Shift to screen coordinates. | 231 // Shift to screen coordinates. |
| 207 if ([controller window]) { | 232 if ([controller window]) { |
| 208 popup_frame = [[controller window] convertRectToScreen:popup_frame]; | 233 popup_frame = [[controller window] convertRectToScreen:popup_frame]; |
| 209 } | 234 } |
| 210 | 235 |
| 211 // Top separator. | 236 // Top separator. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 225 [bottom_separator_view_ setFrame:bottom_separator_frame]; | 250 [bottom_separator_view_ setFrame:bottom_separator_frame]; |
| 226 | 251 |
| 227 // Background view. | 252 // Background view. |
| 228 NSRect background_rect = NSZeroRect; | 253 NSRect background_rect = NSZeroRect; |
| 229 background_rect.size.width = NSWidth(popup_frame); | 254 background_rect.size.width = NSWidth(popup_frame); |
| 230 background_rect.size.height = NSHeight(popup_frame) - | 255 background_rect.size.height = NSHeight(popup_frame) - |
| 231 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); | 256 NSHeight(top_separator_frame) - NSHeight(bottom_separator_frame); |
| 232 background_rect.origin.y = NSMaxY(top_separator_frame); | 257 background_rect.origin.y = NSMaxY(top_separator_frame); |
| 233 [background_view_ setFrame:background_rect]; | 258 [background_view_ setFrame:background_rect]; |
| 234 | 259 |
| 235 // Calculate the width of the table based on backing out the popup's border | 260 // In Material Design, the table is the width of the window. In non-MD, |
| 261 // calculate the width of the table based on backing out the popup's border | |
| 236 // from the width of the field. | 262 // from the width of the field. |
| 237 const CGFloat tableWidth = NSWidth([field_ bounds]); | 263 CGFloat table_width = NSWidth([background_view_ bounds]); |
| 238 DCHECK_GT(tableWidth, 0.0); | 264 bool is_mode_material = ui::MaterialDesignController::IsModeMaterial(); |
| 265 if (!is_mode_material) { | |
| 266 table_width = NSWidth([field_ bounds]); | |
| 267 } | |
| 268 DCHECK_GT(table_width, 0.0); | |
| 239 | 269 |
| 240 // Matrix. | 270 // Matrix. |
| 241 NSPoint field_origin_base = | 271 NSPoint field_origin_base = |
| 242 [field_ convertPoint:[field_ bounds].origin toView:nil]; | 272 [field_ convertPoint:[field_ bounds].origin toView:nil]; |
| 243 NSRect matrix_frame = NSZeroRect; | 273 NSRect matrix_frame = NSZeroRect; |
| 244 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); | 274 matrix_frame.origin.x = 0; |
| 245 matrix_frame.origin.y = kPopupPaddingVertical; | 275 if (!is_mode_material) { |
| 246 matrix_frame.size.width = tableWidth; | 276 matrix_frame.origin.x = field_origin_base.x - NSMinX(anchor_rect_base); |
| 277 } else { | |
| 278 [matrix_ setContentLeftPadding:field_origin_base.x]; | |
| 279 } | |
| 280 matrix_frame.origin.y = PopupPaddingVertical(); | |
| 281 matrix_frame.size.width = table_width; | |
| 247 matrix_frame.size.height = matrixHeight; | 282 matrix_frame.size.height = matrixHeight; |
| 248 [matrix_ setFrame:matrix_frame]; | 283 [matrix_ setFrame:matrix_frame]; |
| 249 [[[matrix_ tableColumns] objectAtIndex:0] setWidth:tableWidth]; | 284 [[[matrix_ tableColumns] objectAtIndex:0] setWidth:table_width]; |
| 250 | 285 |
| 251 // Don't play animation games on first display. | 286 // Don't play animation games on first display. |
| 252 target_popup_frame_ = popup_frame; | 287 target_popup_frame_ = popup_frame; |
| 253 if (![popup_ parentWindow]) { | 288 if (![popup_ parentWindow]) { |
| 254 DCHECK(![popup_ isVisible]); | 289 DCHECK(![popup_ isVisible]); |
| 255 [popup_ setFrame:popup_frame display:NO]; | 290 [popup_ setFrame:popup_frame display:NO]; |
| 256 [[field_ window] addChildWindow:popup_ ordered:NSWindowAbove]; | 291 [[field_ window] addChildWindow:popup_ ordered:NSWindowAbove]; |
| 257 return; | 292 return; |
| 258 } | 293 } |
| 259 DCHECK([popup_ isVisible]); | 294 DCHECK([popup_ isVisible]); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 295 [NSAnimationContext endGrouping]; | 330 [NSAnimationContext endGrouping]; |
| 296 | 331 |
| 297 if (!animate) { | 332 if (!animate) { |
| 298 // Restore the original animations dictionary. This does not reinstate any | 333 // Restore the original animations dictionary. This does not reinstate any |
| 299 // previously running animations. | 334 // previously running animations. |
| 300 [popup_ setAnimations:savedAnimations]; | 335 [popup_ setAnimations:savedAnimations]; |
| 301 } | 336 } |
| 302 } | 337 } |
| 303 | 338 |
| 304 NSImage* OmniboxPopupViewMac::ImageForMatch( | 339 NSImage* OmniboxPopupViewMac::ImageForMatch( |
| 305 const AutocompleteMatch& match) const { | 340 const AutocompleteMatch& match, |
| 341 BOOL ignore_dark_theme) const { | |
| 306 gfx::Image image = model_->GetIconIfExtensionMatch(match); | 342 gfx::Image image = model_->GetIconIfExtensionMatch(match); |
| 307 if (!image.IsEmpty()) | 343 if (!image.IsEmpty()) |
| 308 return image.AsNSImage(); | 344 return image.AsNSImage(); |
| 309 | 345 |
| 310 const int resource_id = model_->IsStarredMatch(match) ? | 346 if (!ui::MaterialDesignController::IsModeMaterial()) { |
| 311 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); | 347 const int resource_id = model_->IsStarredMatch(match) ? |
| 312 return OmniboxViewMac::ImageForResource(resource_id); | 348 IDR_OMNIBOX_STAR : AutocompleteMatch::TypeToIcon(match.type); |
| 349 return OmniboxViewMac::ImageForResource(resource_id); | |
| 350 } | |
| 351 bool is_dark_mode = !ignore_dark_theme && [matrix_ hasDarkTheme]; | |
| 352 const SkColor icon_color = | |
| 353 is_dark_mode ? SkColorSetA(SK_ColorWHITE, 0xCC) : gfx::kChromeIconGrey; | |
| 354 const gfx::VectorIconId vector_icon_id = model_->IsStarredMatch(match) | |
| 355 ? gfx::VectorIconId::LOCATION_BAR_STAR | |
| 356 : AutocompleteMatch::TypeToVectorIcon(match.type); | |
| 357 const int kIconSize = 16; | |
| 358 return NSImageFromImageSkia(gfx::CreateVectorIcon(vector_icon_id, | |
| 359 kIconSize, | |
| 360 icon_color)); | |
| 313 } | 361 } |
| 314 | 362 |
| 315 void OmniboxPopupViewMac::OpenURLForRow(size_t row, | 363 void OmniboxPopupViewMac::OpenURLForRow(size_t row, |
| 316 WindowOpenDisposition disposition) { | 364 WindowOpenDisposition disposition) { |
| 317 DCHECK_LT(row, GetResult().size()); | 365 DCHECK_LT(row, GetResult().size()); |
| 318 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), | 366 omnibox_view_->OpenMatch(GetResult().match_at(row), disposition, GURL(), |
| 319 base::string16(), row); | 367 base::string16(), row); |
| 320 } | 368 } |
| OLD | NEW |