Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/views/autocomplete/autocomplete_popup_contents_view. h" | 5 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view. h" |
| 6 | 6 |
| 7 #include "base/compiler_specific.h" | 7 #include "base/compiler_specific.h" |
| 8 #include "base/utf_string_conversions.h" | 8 #include "base/utf_string_conversions.h" |
| 9 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 9 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
| 10 #include "chrome/browser/instant/instant_confirm_dialog.h" | 10 #include "chrome/browser/instant/instant_confirm_dialog.h" |
| 11 #include "chrome/browser/instant/promo_counter.h" | 11 #include "chrome/browser/instant/promo_counter.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 12 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/ui/omnibox/omnibox_view.h" | 13 #include "chrome/browser/ui/omnibox/omnibox_view.h" |
| 14 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h" | 14 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h" |
| 15 #include "chrome/browser/ui/views/bubble/bubble_border.h" | 15 #include "chrome/browser/ui/views/bubble/bubble_border.h" |
| 16 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 16 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| 17 #include "grit/chromium_strings.h" | 17 #include "grit/chromium_strings.h" |
| 18 #include "grit/generated_resources.h" | 18 #include "grit/generated_resources.h" |
| 19 #include "grit/theme_resources.h" | 19 #include "grit/theme_resources.h" |
| 20 #include "third_party/skia/include/core/SkShader.h" | 20 #include "third_party/skia/include/core/SkShader.h" |
| 21 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
| 22 #include "ui/base/resource/resource_bundle.h" | 22 #include "ui/base/resource/resource_bundle.h" |
| 23 #include "ui/base/theme_provider.h" | 23 #include "ui/base/theme_provider.h" |
| 24 #include "ui/gfx/canvas_skia.h" | 24 #include "ui/gfx/canvas_skia.h" |
| 25 #include "ui/gfx/insets.h" | 25 #include "ui/gfx/insets.h" |
| 26 #include "ui/gfx/path.h" | 26 #include "ui/gfx/path.h" |
| 27 #include "ui/gfx/rect.h" | |
| 27 #include "unicode/ubidi.h" | 28 #include "unicode/ubidi.h" |
| 28 #include "views/controls/button/text_button.h" | 29 #include "views/controls/button/text_button.h" |
| 29 #include "views/controls/label.h" | 30 #include "views/controls/label.h" |
| 30 #include "views/layout/grid_layout.h" | 31 #include "views/layout/grid_layout.h" |
| 31 #include "views/layout/layout_constants.h" | 32 #include "views/layout/layout_constants.h" |
| 32 #include "views/painter.h" | 33 #include "views/painter.h" |
| 33 #include "views/widget/widget.h" | 34 #include "views/widget/widget.h" |
| 34 | 35 |
| 35 #if defined(OS_WIN) | 36 #if defined(OS_WIN) |
| 36 #include <commctrl.h> | 37 #include <commctrl.h> |
| 37 #include <dwmapi.h> | 38 #include <dwmapi.h> |
| 38 #include <objidl.h> | 39 #include <objidl.h> |
| 39 | 40 |
| 40 #include "base/win/scoped_gdi_object.h" | 41 #include "base/win/scoped_gdi_object.h" |
| 41 #include "views/widget/native_widget_win.h" | 42 #include "views/widget/native_widget_win.h" |
| 42 #endif | 43 #endif |
| 43 | 44 |
| 44 #if defined(TOOLKIT_USES_GTK) | 45 #if defined(TOOLKIT_USES_GTK) |
| 45 #include "ui/gfx/skia_utils_gtk.h" | 46 #include "ui/gfx/skia_utils_gtk.h" |
| 46 #endif | 47 #endif |
| 47 | 48 |
| 48 namespace { | 49 namespace { |
| 49 | 50 |
| 50 const SkAlpha kGlassPopupAlpha = 240; | 51 const SkAlpha kGlassPopupAlpha = 240; |
| 51 const SkAlpha kOpaquePopupAlpha = 255; | 52 const SkAlpha kOpaquePopupAlpha = 255; |
| 53 | |
| 54 // An alpha value to apply to the AutocompleteResultView dim text color | |
| 55 // that will help the resulting color (used for dividing result and keyword | |
| 56 // views) match the popup border color. | |
| 57 const SkAlpha kResultDividerAlpha = 170; | |
| 58 | |
| 52 // The size delta between the font used for the edit and the result rows. Passed | 59 // The size delta between the font used for the edit and the result rows. Passed |
| 53 // to gfx::Font::DeriveFont. | 60 // to gfx::Font::DeriveFont. |
| 54 #if defined(OS_CHROMEOS) | 61 #if defined(OS_CHROMEOS) |
| 55 // Don't adjust the size on Chrome OS (http://crbug.com/61433). | 62 // Don't adjust the size on Chrome OS (http://crbug.com/61433). |
| 56 const int kEditFontAdjust = 0; | 63 const int kEditFontAdjust = 0; |
| 57 #else | 64 #else |
| 58 const int kEditFontAdjust = -1; | 65 const int kEditFontAdjust = -1; |
| 59 #endif | 66 #endif |
| 60 | 67 |
| 61 // Horizontal padding between the buttons on the opt in promo. | 68 // Horizontal padding between the buttons on the opt in promo. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 135 } // namespace | 142 } // namespace |
| 136 | 143 |
| 137 class AutocompletePopupContentsView::AutocompletePopupWidget | 144 class AutocompletePopupContentsView::AutocompletePopupWidget |
| 138 : public views::Widget, | 145 : public views::Widget, |
| 139 public base::SupportsWeakPtr<AutocompletePopupWidget> { | 146 public base::SupportsWeakPtr<AutocompletePopupWidget> { |
| 140 public: | 147 public: |
| 141 AutocompletePopupWidget() {} | 148 AutocompletePopupWidget() {} |
| 142 virtual ~AutocompletePopupWidget() {} | 149 virtual ~AutocompletePopupWidget() {} |
| 143 | 150 |
| 144 private: | 151 private: |
| 145 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); | 152 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); |
| 146 }; | 153 }; |
| 147 | 154 |
| 148 class AutocompletePopupContentsView::InstantOptInView | 155 class AutocompletePopupContentsView::InstantOptInView |
| 149 : public views::View, | 156 : public views::View, |
| 150 public views::ButtonListener { | 157 public views::ButtonListener { |
| 151 public: | 158 public: |
| 152 InstantOptInView(AutocompletePopupContentsView* contents_view, | 159 InstantOptInView(AutocompletePopupContentsView* contents_view, |
| 153 const gfx::Font& label_font, | 160 const gfx::Font& label_font, |
| 154 const gfx::Font& button_font) | 161 const gfx::Font& button_font) |
| 155 : contents_view_(contents_view), | 162 : contents_view_(contents_view), |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 result_bold_font_(result_font_.DeriveFont(0, gfx::Font::BOLD)), | 246 result_bold_font_(result_font_.DeriveFont(0, gfx::Font::BOLD)), |
| 240 ignore_mouse_drag_(false), | 247 ignore_mouse_drag_(false), |
| 241 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { | 248 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { |
| 242 // The following little dance is required because set_border() requires a | 249 // The following little dance is required because set_border() requires a |
| 243 // pointer to a non-const object. | 250 // pointer to a non-const object. |
| 244 BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::NONE); | 251 BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::NONE); |
| 245 bubble_border_ = bubble_border; | 252 bubble_border_ = bubble_border; |
| 246 set_border(bubble_border); | 253 set_border(bubble_border); |
| 247 // The contents is owned by the LocationBarView. | 254 // The contents is owned by the LocationBarView. |
| 248 set_parent_owned(false); | 255 set_parent_owned(false); |
| 256 | |
| 257 for (size_t i = 0; i < AutocompleteResult::kMaxMatches * 2; ++i) { | |
| 258 AutocompleteResultView* result_view = | |
| 259 CreateResultView(this, i, result_font_, result_bold_font_); | |
| 260 AddChildViewAt(result_view, static_cast<int>(i)); | |
| 261 result_view->SetVisible(false); | |
| 262 | |
| 263 if (i < AutocompleteResult::kMaxMatches) { | |
|
sky
2011/08/09 00:32:51
Ick, how about two loops. But as I mentioned last
| |
| 264 keyword_animations_.push_back(new ui::SlideAnimation(this)); | |
|
sky
2011/08/09 00:32:51
Create one AnimationContainer and have all animati
| |
| 265 } | |
| 266 } | |
| 249 } | 267 } |
| 250 | 268 |
| 251 AutocompletePopupContentsView::~AutocompletePopupContentsView() { | 269 AutocompletePopupContentsView::~AutocompletePopupContentsView() { |
| 252 // We don't need to do anything with |popup_| here. The OS either has already | 270 // We don't need to do anything with |popup_| here. The OS either has already |
| 253 // closed the window, in which case it's been deleted, or it will soon, in | 271 // closed the window, in which case it's been deleted, or it will soon, in |
| 254 // which case there's nothing we need to do. | 272 // which case there's nothing we need to do. |
| 255 } | 273 } |
| 256 | 274 |
| 257 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { | 275 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { |
| 258 if (!size_animation_.is_animating()) | 276 if (!size_animation_.is_animating()) |
| 259 return target_bounds_; | 277 return target_bounds_; |
| 260 | 278 |
| 261 gfx::Rect current_frame_bounds = start_bounds_; | 279 gfx::Rect current_frame_bounds = start_bounds_; |
| 262 int total_height_delta = target_bounds_.height() - start_bounds_.height(); | 280 int total_height_delta = target_bounds_.height() - start_bounds_.height(); |
| 263 // Round |current_height_delta| instead of truncating so we won't leave single | 281 // Round |current_height_delta| instead of truncating so we won't leave single |
| 264 // white pixels at the bottom of the popup as long when animating very small | 282 // white pixels at the bottom of the popup as long when animating very small |
| 265 // height differences. | 283 // height differences. |
| 266 int current_height_delta = static_cast<int>( | 284 int current_height_delta = static_cast<int>( |
| 267 size_animation_.GetCurrentValue() * total_height_delta - 0.5); | 285 size_animation_.GetCurrentValue() * total_height_delta - 0.5); |
| 268 current_frame_bounds.set_height( | 286 current_frame_bounds.set_height( |
| 269 current_frame_bounds.height() + current_height_delta); | 287 current_frame_bounds.height() + current_height_delta); |
| 270 return current_frame_bounds; | 288 return current_frame_bounds; |
| 271 } | 289 } |
| 272 | 290 |
| 273 void AutocompletePopupContentsView::LayoutChildren() { | 291 void AutocompletePopupContentsView::LayoutChildren() { |
| 274 gfx::Rect contents_rect = GetContentsBounds(); | 292 gfx::Rect contents_rect = GetContentsBounds(); |
| 275 int top = contents_rect.y(); | 293 int top = contents_rect.y(); |
| 276 for (int i = 0; i < child_count(); ++i) { | 294 |
| 277 View* v = child_at(i); | 295 for (size_t i = 0; i < AutocompleteResult::kMaxMatches * 2; i += 2) { |
| 278 if (v->IsVisible()) { | 296 View* result = child_at(i); |
| 279 v->SetBounds(contents_rect.x(), top, contents_rect.width(), | 297 if (!result->IsVisible()) |
| 280 v->GetPreferredSize().height()); | 298 continue; |
| 281 top = v->bounds().bottom(); | 299 |
| 300 AutocompleteResultView* keyword = | |
| 301 static_cast<AutocompleteResultView*>(child_at(i + 1)); | |
| 302 if (keyword->IsVisible()) { | |
| 303 const int collapsed_width = keyword->GetCollapsedSize().width() + | |
| 304 LocationBarView::kEdgeItemPadding; | |
| 305 const int kw_collapsed_x = contents_rect.width() - collapsed_width; | |
| 306 const int kw_x = contents_rect.width() - | |
| 307 keyword_animations_[i / 2]->CurrentValueBetween(collapsed_width, | |
| 308 kw_collapsed_x); | |
| 309 | |
| 310 result->SetBounds(contents_rect.x(), top, | |
| 311 kw_x - LocationBarView::kNormalHorizontalEdgeThickness, | |
| 312 result->GetPreferredSize().height()); | |
| 313 keyword->SetBounds(contents_rect.x() + kw_x, top, | |
| 314 contents_rect.width() - kw_x, keyword->GetPreferredSize().height()); | |
| 315 } else { | |
| 316 result->SetBounds(contents_rect.x(), top, contents_rect.width(), | |
| 317 result->GetPreferredSize().height()); | |
| 282 } | 318 } |
| 319 top = result->bounds().bottom(); | |
| 283 } | 320 } |
| 321 | |
| 322 if (opt_in_view_ && opt_in_view_->IsVisible()) | |
| 323 opt_in_view_->SetBounds(contents_rect.x(), top, contents_rect.width(), | |
| 324 opt_in_view_->GetPreferredSize().height()); | |
| 284 } | 325 } |
| 285 | 326 |
| 286 //////////////////////////////////////////////////////////////////////////////// | 327 //////////////////////////////////////////////////////////////////////////////// |
| 287 // AutocompletePopupContentsView, AutocompletePopupView overrides: | 328 // AutocompletePopupContentsView, AutocompletePopupView overrides: |
| 288 | 329 |
| 289 bool AutocompletePopupContentsView::IsOpen() const { | 330 bool AutocompletePopupContentsView::IsOpen() const { |
| 290 return (popup_ != NULL); | 331 return (popup_ != NULL); |
| 291 } | 332 } |
| 292 | 333 |
| 293 void AutocompletePopupContentsView::InvalidateLine(size_t line) { | 334 void AutocompletePopupContentsView::InvalidateLine(size_t line) { |
| 294 child_at(static_cast<int>(line))->SchedulePaint(); | 335 child_at(static_cast<int>(line * 2))->SchedulePaint(); |
| 336 child_at(static_cast<int>(line * 2 + 1))->SchedulePaint(); | |
| 337 | |
| 338 if (line == model_->selected_line() && | |
| 339 model_->selected_match() == AutocompletePopupModel::KEYWORD) | |
| 340 keyword_animations_[line]->Show(); | |
| 341 else | |
| 342 keyword_animations_[line]->Hide(); | |
| 295 } | 343 } |
| 296 | 344 |
| 297 void AutocompletePopupContentsView::UpdatePopupAppearance() { | 345 void AutocompletePopupContentsView::UpdatePopupAppearance() { |
| 298 if (model_->result().empty()) { | 346 if (model_->result().empty()) { |
| 299 // No matches, close any existing popup. | 347 // No matches, close any existing popup. |
| 300 if (popup_ != NULL) { | 348 if (popup_ != NULL) { |
| 301 size_animation_.Stop(); | 349 size_animation_.Stop(); |
| 350 | |
| 351 for (SlideAnimations::iterator i(keyword_animations_.begin()); | |
| 352 i != keyword_animations_.end(); ++i) | |
| 353 (*i)->Stop(); | |
| 354 | |
| 302 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack | 355 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack |
| 303 // triggered by the popup receiving a message (e.g. LBUTTONUP), and | 356 // triggered by the popup receiving a message (e.g. LBUTTONUP), and |
| 304 // destroying the popup would cause us to read garbage when we unwind back | 357 // destroying the popup would cause us to read garbage when we unwind back |
| 305 // to that level. | 358 // to that level. |
| 306 popup_->Close(); // This will eventually delete the popup. | 359 popup_->Close(); // This will eventually delete the popup. |
| 307 popup_.reset(); | 360 popup_.reset(); |
| 308 } | 361 } |
| 309 return; | 362 return; |
| 310 } | 363 } |
| 311 | 364 |
| 312 // Update the match cached by each row, in the process of doing so make sure | 365 // Update the match cached by each row, in the process of doing so make sure |
| 313 // we have enough row views. | 366 // we have enough row views. |
| 314 size_t child_rv_count = child_count(); | 367 size_t child_rv_count = child_count(); |
| 315 if (opt_in_view_) { | 368 if (opt_in_view_) { |
| 316 DCHECK(child_rv_count > 0); | 369 DCHECK(child_rv_count > 0); |
| 317 child_rv_count--; | 370 child_rv_count--; |
| 318 } | 371 } |
| 319 for (size_t i = 0; i < model_->result().size(); ++i) { | 372 const size_t result_size = model_->result().size(); |
| 320 AutocompleteResultView* result_view; | 373 for (size_t i = 0; i < result_size; ++i) { |
| 321 if (i >= child_rv_count) { | 374 const AutocompleteMatch& match = GetMatchAtIndex(i); |
| 322 result_view = | 375 AutocompleteResultView* view = static_cast<AutocompleteResultView*>( |
| 323 CreateResultView(this, i, result_font_, result_bold_font_); | 376 child_at(i * 2)); |
| 324 AddChildViewAt(result_view, static_cast<int>(i)); | 377 view->SetMatch(match); |
| 325 } else { | 378 view->SetVisible(true); |
| 326 result_view = static_cast<AutocompleteResultView*>(child_at(i)); | 379 |
| 327 result_view->SetVisible(true); | 380 view = static_cast<AutocompleteResultView*>(child_at(i * 2 + 1)); |
| 328 } | 381 view->SetVisible(match.associated_keyword.get() != NULL); |
| 329 result_view->SetMatch(GetMatchAtIndex(i)); | 382 if (view->IsVisible()) |
| 383 view->SetMatch(*match.associated_keyword); | |
| 384 | |
| 385 keyword_animations_[i]->Reset(); | |
| 330 } | 386 } |
| 331 for (size_t i = model_->result().size(); i < child_rv_count; ++i) | 387 for (size_t i = result_size * 2; i < child_rv_count; ++i) |
| 332 child_at(i)->SetVisible(false); | 388 child_at(i)->SetVisible(false); |
| 333 | 389 |
| 334 PromoCounter* counter = model_->profile()->GetInstantPromoCounter(); | 390 PromoCounter* counter = model_->profile()->GetInstantPromoCounter(); |
| 335 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { | 391 if (!opt_in_view_ && counter && counter->ShouldShow(base::Time::Now())) { |
| 336 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); | 392 opt_in_view_ = new InstantOptInView(this, result_bold_font_, result_font_); |
| 337 AddChildView(opt_in_view_); | 393 AddChildView(opt_in_view_); |
| 338 } else if (opt_in_view_ && (!counter || | 394 } else if (opt_in_view_ && (!counter || |
| 339 !counter->ShouldShow(base::Time::Now()))) { | 395 !counter->ShouldShow(base::Time::Now()))) { |
| 340 delete opt_in_view_; | 396 delete opt_in_view_; |
| 341 opt_in_view_ = NULL; | 397 opt_in_view_ = NULL; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 368 // Animate the popup shrinking, but don't animate growing larger since that | 424 // Animate the popup shrinking, but don't animate growing larger since that |
| 369 // would make the popup feel less responsive. | 425 // would make the popup feel less responsive. |
| 370 start_bounds_ = GetWidget()->GetWindowScreenBounds(); | 426 start_bounds_ = GetWidget()->GetWindowScreenBounds(); |
| 371 if (target_bounds_.height() < start_bounds_.height()) | 427 if (target_bounds_.height() < start_bounds_.height()) |
| 372 size_animation_.Show(); | 428 size_animation_.Show(); |
| 373 else | 429 else |
| 374 start_bounds_ = target_bounds_; | 430 start_bounds_ = target_bounds_; |
| 375 popup_->SetBounds(GetPopupBounds()); | 431 popup_->SetBounds(GetPopupBounds()); |
| 376 } | 432 } |
| 377 | 433 |
| 378 SchedulePaint(); | 434 Layout(); |
| 379 } | 435 } |
| 380 | 436 |
| 381 gfx::Rect AutocompletePopupContentsView::GetTargetBounds() { | 437 gfx::Rect AutocompletePopupContentsView::GetTargetBounds() { |
| 382 return target_bounds_; | 438 return target_bounds_; |
| 383 } | 439 } |
| 384 | 440 |
| 385 void AutocompletePopupContentsView::PaintUpdatesNow() { | 441 void AutocompletePopupContentsView::PaintUpdatesNow() { |
| 386 // TODO(beng): remove this from the interface. | 442 // TODO(beng): remove this from the interface. |
| 387 } | 443 } |
| 388 | 444 |
| 389 void AutocompletePopupContentsView::OnDragCanceled() { | 445 void AutocompletePopupContentsView::OnDragCanceled() { |
| 390 ignore_mouse_drag_ = true; | 446 ignore_mouse_drag_ = true; |
| 391 } | 447 } |
| 392 | 448 |
| 393 //////////////////////////////////////////////////////////////////////////////// | 449 //////////////////////////////////////////////////////////////////////////////// |
| 394 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 450 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: |
| 395 | 451 |
| 396 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 452 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { |
| 397 return HasMatchAt(index) ? index == model_->selected_line() : false; | 453 size_t selected_line = model_->selected_line() * 2; |
| 454 | |
| 455 if (model_->selected_match() == AutocompletePopupModel::KEYWORD) | |
| 456 selected_line++; | |
| 457 | |
| 458 return index == selected_line; | |
| 398 } | 459 } |
| 399 | 460 |
| 400 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 461 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { |
| 401 return HasMatchAt(index) ? index == model_->hovered_line() : false; | 462 return index == model_->hovered_line() * 2; |
| 402 } | 463 } |
| 403 | 464 |
| 404 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( | 465 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( |
| 405 size_t index) const { | 466 size_t index) const { |
| 406 if (!HasMatchAt(index)) | 467 if (!HasMatchAt(index)) |
| 407 return NULL; | 468 return NULL; |
| 408 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); | 469 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); |
| 409 } | 470 } |
| 410 | 471 |
| 411 //////////////////////////////////////////////////////////////////////////////// | 472 //////////////////////////////////////////////////////////////////////////////// |
| 412 // AutocompletePopupContentsView, AnimationDelegate implementation: | 473 // AutocompletePopupContentsView, AnimationDelegate implementation: |
| 413 | 474 |
| 414 void AutocompletePopupContentsView::AnimationProgressed( | 475 void AutocompletePopupContentsView::AnimationProgressed( |
| 415 const ui::Animation* animation) { | 476 const ui::Animation* animation) { |
| 416 // We should only be running the animation when the popup is already visible. | 477 // We should only be running the animation when the popup is already visible. |
| 417 DCHECK(popup_ != NULL); | 478 DCHECK(popup_ != NULL); |
| 418 popup_->SetBounds(GetPopupBounds()); | 479 popup_->SetBounds(GetPopupBounds()); |
| 480 | |
| 481 Layout(); | |
| 419 } | 482 } |
| 420 | 483 |
| 421 //////////////////////////////////////////////////////////////////////////////// | 484 //////////////////////////////////////////////////////////////////////////////// |
| 422 // AutocompletePopupContentsView, views::View overrides: | 485 // AutocompletePopupContentsView, views::View overrides: |
| 423 | 486 |
| 424 void AutocompletePopupContentsView::Layout() { | 487 void AutocompletePopupContentsView::Layout() { |
| 425 UpdateBlurRegion(); | 488 UpdateBlurRegion(); |
| 426 | 489 |
| 427 // Size our children to the available content area. | 490 // Size our children to the available content area. |
| 428 LayoutChildren(); | 491 LayoutChildren(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); | 565 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); |
| 503 } | 566 } |
| 504 | 567 |
| 505 //////////////////////////////////////////////////////////////////////////////// | 568 //////////////////////////////////////////////////////////////////////////////// |
| 506 // AutocompletePopupContentsView, protected: | 569 // AutocompletePopupContentsView, protected: |
| 507 | 570 |
| 508 void AutocompletePopupContentsView::PaintResultViews(gfx::CanvasSkia* canvas) { | 571 void AutocompletePopupContentsView::PaintResultViews(gfx::CanvasSkia* canvas) { |
| 509 canvas->drawColor(AutocompleteResultView::GetColor( | 572 canvas->drawColor(AutocompleteResultView::GetColor( |
| 510 AutocompleteResultView::NORMAL, AutocompleteResultView::BACKGROUND)); | 573 AutocompleteResultView::NORMAL, AutocompleteResultView::BACKGROUND)); |
| 511 View::PaintChildren(canvas); | 574 View::PaintChildren(canvas); |
| 575 | |
| 576 // Draw dividing lines between results and keyword views. | |
| 577 SkColor divider_color = SkColorSetA(AutocompleteResultView::GetColor( | |
| 578 AutocompleteResultView::NORMAL, AutocompleteResultView::DIMMED_TEXT), | |
| 579 kResultDividerAlpha); | |
| 580 | |
| 581 for (size_t i = 0; i < model_->result().size(); ++i) { | |
| 582 if (model_->result().match_at(i).associated_keyword.get()) { | |
| 583 views::View* child = child_at(i * 2); | |
| 584 canvas->FillRectInt(divider_color, child->bounds().right(), | |
| 585 child->bounds().y(), LocationBarView::kNormalHorizontalEdgeThickness, | |
| 586 child->bounds().height()); | |
| 587 } | |
| 588 } | |
| 512 } | 589 } |
| 513 | 590 |
| 514 int AutocompletePopupContentsView::CalculatePopupHeight() { | 591 int AutocompletePopupContentsView::CalculatePopupHeight() { |
| 515 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); | 592 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); |
| 516 int popup_height = 0; | 593 int popup_height = 0; |
| 517 for (size_t i = 0; i < model_->result().size(); ++i) | 594 for (size_t i = 0; i < model_->result().size(); ++i) |
| 518 popup_height += child_at(i)->GetPreferredSize().height(); | 595 popup_height += child_at(i)->GetPreferredSize().height(); |
| 519 return popup_height + | 596 return popup_height + |
| 520 (opt_in_view_ ? opt_in_view_->GetPreferredSize().height() : 0); | 597 (opt_in_view_ ? opt_in_view_->GetPreferredSize().height() : 0); |
| 521 } | 598 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 638 void AutocompletePopupContentsView::OpenIndex( | 715 void AutocompletePopupContentsView::OpenIndex( |
| 639 size_t index, | 716 size_t index, |
| 640 WindowOpenDisposition disposition) { | 717 WindowOpenDisposition disposition) { |
| 641 if (!HasMatchAt(index)) | 718 if (!HasMatchAt(index)) |
| 642 return; | 719 return; |
| 643 | 720 |
| 644 // OpenMatch() may close the popup, which will clear the result set and, by | 721 // OpenMatch() may close the popup, which will clear the result set and, by |
| 645 // extension, |match| and its contents. So copy the relevant match out to | 722 // extension, |match| and its contents. So copy the relevant match out to |
| 646 // make sure it stays alive until the call completes. | 723 // make sure it stays alive until the call completes. |
| 647 AutocompleteMatch match = model_->result().match_at(index); | 724 AutocompleteMatch match = model_->result().match_at(index); |
| 648 string16 keyword; | |
| 649 const bool is_keyword_hint = model_->GetKeywordForMatch(match, &keyword); | |
| 650 omnibox_view_->OpenMatch(match, disposition, GURL(), index, | 725 omnibox_view_->OpenMatch(match, disposition, GURL(), index, |
| 651 is_keyword_hint ? string16() : keyword); | 726 match.keyword); |
| 652 } | 727 } |
| 653 | 728 |
| 654 size_t AutocompletePopupContentsView::GetIndexForPoint( | 729 size_t AutocompletePopupContentsView::GetIndexForPoint( |
| 655 const gfx::Point& point) { | 730 const gfx::Point& point) { |
| 656 if (!HitTest(point)) | 731 if (!HitTest(point)) |
| 657 return AutocompletePopupModel::kNoMatch; | 732 return AutocompletePopupModel::kNoMatch; |
| 658 | 733 |
| 659 int nb_match = model_->result().size(); | 734 int nb_match = model_->result().size(); |
| 660 DCHECK(nb_match <= child_count()); | 735 DCHECK(nb_match <= child_count()); |
| 661 for (int i = 0; i < nb_match; ++i) { | 736 for (int i = 0; i < nb_match; ++i) { |
| 662 views::View* child = child_at(i); | 737 views::View* child = child_at(i * 2); |
| 663 gfx::Point point_in_child_coords(point); | 738 gfx::Point point_in_child_coords(point); |
| 664 View::ConvertPointToView(this, child, &point_in_child_coords); | 739 View::ConvertPointToView(this, child, &point_in_child_coords); |
| 665 if (child->HitTest(point_in_child_coords)) | 740 if (child->HitTest(point_in_child_coords)) |
| 666 return i; | 741 return i; |
| 667 } | 742 } |
| 668 return AutocompletePopupModel::kNoMatch; | 743 return AutocompletePopupModel::kNoMatch; |
| 669 } | 744 } |
| 670 | 745 |
| 671 gfx::Rect AutocompletePopupContentsView::CalculateTargetBounds(int h) { | 746 gfx::Rect AutocompletePopupContentsView::CalculateTargetBounds(int h) { |
| 672 gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds()); | 747 gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds()); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 696 opt_in_view_ = NULL; | 771 opt_in_view_ = NULL; |
| 697 PromoCounter* counter = model_->profile()->GetInstantPromoCounter(); | 772 PromoCounter* counter = model_->profile()->GetInstantPromoCounter(); |
| 698 DCHECK(counter); | 773 DCHECK(counter); |
| 699 counter->Hide(); | 774 counter->Hide(); |
| 700 if (opt_in) { | 775 if (opt_in) { |
| 701 browser::ShowInstantConfirmDialogIfNecessary( | 776 browser::ShowInstantConfirmDialogIfNecessary( |
| 702 location_bar_->GetWidget()->GetNativeWindow(), model_->profile()); | 777 location_bar_->GetWidget()->GetNativeWindow(), model_->profile()); |
| 703 } | 778 } |
| 704 UpdatePopupAppearance(); | 779 UpdatePopupAppearance(); |
| 705 } | 780 } |
| OLD | NEW |