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/views/autocomplete/autocomplete_popup_contents_view. h" | 5 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <commctrl.h> | 8 #include <commctrl.h> |
| 9 #include <dwmapi.h> | 9 #include <dwmapi.h> |
| 10 #include <objidl.h> | 10 #include <objidl.h> |
| 11 #endif | 11 #endif |
| 12 | 12 |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/utf_string_conversions.h" | 14 #include "base/utf_string_conversions.h" |
| 15 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 15 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
| 16 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/themes/theme_service.h" | 17 #include "chrome/browser/themes/theme_service.h" |
| 18 #include "chrome/browser/ui/omnibox/omnibox_view.h" | 18 #include "chrome/browser/ui/omnibox/omnibox_view.h" |
| 19 #include "chrome/browser/ui/views/autocomplete/autocomplete_result_view.h" | |
| 20 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" | 19 #include "chrome/browser/ui/views/location_bar/location_bar_view.h" |
| 21 #include "chrome/browser/ui/views/autocomplete/touch_autocomplete_popup_contents _view.h" | 20 #include "chrome/browser/ui/views/omnibox/omnibox_result_view.h" |
| 21 #include "chrome/browser/ui/views/omnibox/touch_omnibox_popup_contents_view.h" | |
| 22 #include "grit/chromium_strings.h" | 22 #include "grit/chromium_strings.h" |
| 23 #include "grit/generated_resources.h" | 23 #include "grit/generated_resources.h" |
| 24 #include "grit/theme_resources.h" | 24 #include "grit/theme_resources.h" |
| 25 #include "third_party/skia/include/core/SkShader.h" | 25 #include "third_party/skia/include/core/SkShader.h" |
| 26 #include "ui/base/l10n/l10n_util.h" | 26 #include "ui/base/l10n/l10n_util.h" |
| 27 #include "ui/base/layout.h" | 27 #include "ui/base/layout.h" |
| 28 #include "ui/base/resource/resource_bundle.h" | 28 #include "ui/base/resource/resource_bundle.h" |
| 29 #include "ui/base/theme_provider.h" | 29 #include "ui/base/theme_provider.h" |
| 30 #include "ui/gfx/canvas.h" | 30 #include "ui/gfx/canvas.h" |
| 31 #include "ui/gfx/insets.h" | 31 #include "ui/gfx/insets.h" |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 58 // to gfx::Font::DeriveFont. | 58 // to gfx::Font::DeriveFont. |
| 59 #if defined(OS_CHROMEOS) | 59 #if defined(OS_CHROMEOS) |
| 60 // Don't adjust the size on Chrome OS (http://crbug.com/61433). | 60 // Don't adjust the size on Chrome OS (http://crbug.com/61433). |
| 61 const int kEditFontAdjust = 0; | 61 const int kEditFontAdjust = 0; |
| 62 #else | 62 #else |
| 63 const int kEditFontAdjust = -1; | 63 const int kEditFontAdjust = -1; |
| 64 #endif | 64 #endif |
| 65 | 65 |
| 66 } // namespace | 66 } // namespace |
| 67 | 67 |
| 68 class AutocompletePopupContentsView::AutocompletePopupWidget | 68 class OmniboxPopupContentsView::AutocompletePopupWidget |
| 69 : public views::Widget, | 69 : public views::Widget, |
| 70 public base::SupportsWeakPtr<AutocompletePopupWidget> { | 70 public base::SupportsWeakPtr<AutocompletePopupWidget> { |
| 71 public: | 71 public: |
| 72 AutocompletePopupWidget() {} | 72 AutocompletePopupWidget() {} |
| 73 virtual ~AutocompletePopupWidget() {} | 73 virtual ~AutocompletePopupWidget() {} |
| 74 | 74 |
| 75 private: | 75 private: |
| 76 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); | 76 DISALLOW_COPY_AND_ASSIGN(AutocompletePopupWidget); |
| 77 }; | 77 }; |
| 78 | 78 |
| 79 //////////////////////////////////////////////////////////////////////////////// | 79 //////////////////////////////////////////////////////////////////////////////// |
| 80 // AutocompletePopupContentsView, public: | 80 // OmniboxPopupContentsView, public: |
| 81 | 81 |
| 82 AutocompletePopupContentsView* | 82 OmniboxPopupContentsView* OmniboxPopupContentsView::CreateForEnvironment( |
| 83 AutocompletePopupContentsView::CreateForEnvironment( | 83 const gfx::Font& font, |
| 84 const gfx::Font& font, | 84 OmniboxView* omnibox_view, |
| 85 OmniboxView* omnibox_view, | 85 AutocompleteEditModel* edit_model, |
| 86 AutocompleteEditModel* edit_model, | 86 views::View* location_bar) { |
| 87 views::View* location_bar) { | 87 OmniboxPopupContentsView* view = NULL; |
| 88 AutocompletePopupContentsView* view = NULL; | |
| 89 if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { | 88 if (ui::GetDisplayLayout() == ui::LAYOUT_TOUCH) { |
| 90 view = new TouchAutocompletePopupContentsView( | 89 view = new TouchOmniboxPopupContentsView( |
| 91 font, omnibox_view, edit_model, location_bar); | 90 font, omnibox_view, edit_model, location_bar); |
| 92 } else { | 91 } else { |
| 93 view = new AutocompletePopupContentsView( | 92 view = new OmniboxPopupContentsView( |
| 94 font, omnibox_view, edit_model, location_bar); | 93 font, omnibox_view, edit_model, location_bar); |
| 95 } | 94 } |
| 96 | 95 |
| 97 view->Init(); | 96 view->Init(); |
| 98 return view; | 97 return view; |
| 99 } | 98 } |
| 100 | 99 |
| 101 AutocompletePopupContentsView::AutocompletePopupContentsView( | 100 OmniboxPopupContentsView::OmniboxPopupContentsView( |
| 102 const gfx::Font& font, | 101 const gfx::Font& font, |
| 103 OmniboxView* omnibox_view, | 102 OmniboxView* omnibox_view, |
| 104 AutocompleteEditModel* edit_model, | 103 AutocompleteEditModel* edit_model, |
| 105 views::View* location_bar) | 104 views::View* location_bar) |
| 106 : model_(new AutocompletePopupModel(this, edit_model)), | 105 : model_(new AutocompletePopupModel(this, edit_model)), |
| 107 omnibox_view_(omnibox_view), | 106 omnibox_view_(omnibox_view), |
| 108 profile_(edit_model->profile()), | 107 profile_(edit_model->profile()), |
| 109 location_bar_(location_bar), | 108 location_bar_(location_bar), |
| 110 result_font_(font.DeriveFont(kEditFontAdjust)), | 109 result_font_(font.DeriveFont(kEditFontAdjust)), |
| 111 result_bold_font_(result_font_.DeriveFont(0, gfx::Font::BOLD)), | 110 result_bold_font_(result_font_.DeriveFont(0, gfx::Font::BOLD)), |
| 112 ignore_mouse_drag_(false), | 111 ignore_mouse_drag_(false), |
| 113 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { | 112 ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) { |
| 114 // The following little dance is required because set_border() requires a | 113 // The following little dance is required because set_border() requires a |
| 115 // pointer to a non-const object. | 114 // pointer to a non-const object. |
| 116 views::BubbleBorder* bubble_border = | 115 views::BubbleBorder* bubble_border = |
| 117 new views::BubbleBorder(views::BubbleBorder::NONE, | 116 new views::BubbleBorder(views::BubbleBorder::NONE, |
| 118 views::BubbleBorder::NO_SHADOW); | 117 views::BubbleBorder::NO_SHADOW); |
| 119 bubble_border_ = bubble_border; | 118 bubble_border_ = bubble_border; |
| 120 set_border(bubble_border); | 119 set_border(bubble_border); |
| 121 // The contents is owned by the LocationBarView. | 120 // The contents is owned by the LocationBarView. |
| 122 set_owned_by_client(); | 121 set_owned_by_client(); |
| 123 } | 122 } |
| 124 | 123 |
| 125 void AutocompletePopupContentsView::Init() { | 124 void OmniboxPopupContentsView::Init() { |
| 126 // This can't be done in the constructor as at that point we aren't | 125 // This can't be done in the constructor as at that point we aren't |
| 127 // necessarily our final class yet, and we may have subclasses | 126 // necessarily our final class yet, and we may have subclasses |
| 128 // overriding CreateResultView. | 127 // overriding CreateResultView. |
| 129 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { | 128 for (size_t i = 0; i < AutocompleteResult::kMaxMatches; ++i) { |
| 130 AutocompleteResultView* result_view = | 129 OmniboxResultView* result_view = |
| 131 CreateResultView(this, i, result_font_, result_bold_font_); | 130 CreateResultView(this, i, result_font_, result_bold_font_); |
| 132 result_view->SetVisible(false); | 131 result_view->SetVisible(false); |
| 133 AddChildViewAt(result_view, static_cast<int>(i)); | 132 AddChildViewAt(result_view, static_cast<int>(i)); |
| 134 } | 133 } |
| 135 } | 134 } |
| 136 | 135 |
| 137 AutocompletePopupContentsView::~AutocompletePopupContentsView() { | 136 OmniboxPopupContentsView::~OmniboxPopupContentsView() { |
| 138 // We don't need to do anything with |popup_| here. The OS either has already | 137 // We don't need to do anything with |popup_| here. The OS either has already |
| 139 // closed the window, in which case it's been deleted, or it will soon, in | 138 // closed the window, in which case it's been deleted, or it will soon, in |
| 140 // which case there's nothing we need to do. | 139 // which case there's nothing we need to do. |
| 141 } | 140 } |
| 142 | 141 |
| 143 gfx::Rect AutocompletePopupContentsView::GetPopupBounds() const { | 142 gfx::Rect OmniboxPopupContentsView::GetPopupBounds() const { |
| 144 if (!size_animation_.is_animating()) | 143 if (!size_animation_.is_animating()) |
| 145 return target_bounds_; | 144 return target_bounds_; |
| 146 | 145 |
| 147 gfx::Rect current_frame_bounds = start_bounds_; | 146 gfx::Rect current_frame_bounds = start_bounds_; |
| 148 int total_height_delta = target_bounds_.height() - start_bounds_.height(); | 147 int total_height_delta = target_bounds_.height() - start_bounds_.height(); |
| 149 // Round |current_height_delta| instead of truncating so we won't leave single | 148 // Round |current_height_delta| instead of truncating so we won't leave single |
| 150 // white pixels at the bottom of the popup as long when animating very small | 149 // white pixels at the bottom of the popup as long when animating very small |
| 151 // height differences. | 150 // height differences. |
| 152 int current_height_delta = static_cast<int>( | 151 int current_height_delta = static_cast<int>( |
| 153 size_animation_.GetCurrentValue() * total_height_delta - 0.5); | 152 size_animation_.GetCurrentValue() * total_height_delta - 0.5); |
| 154 current_frame_bounds.set_height( | 153 current_frame_bounds.set_height( |
| 155 current_frame_bounds.height() + current_height_delta); | 154 current_frame_bounds.height() + current_height_delta); |
| 156 return current_frame_bounds; | 155 return current_frame_bounds; |
| 157 } | 156 } |
| 158 | 157 |
| 159 void AutocompletePopupContentsView::LayoutChildren() { | 158 void OmniboxPopupContentsView::LayoutChildren() { |
| 160 gfx::Rect contents_rect = GetContentsBounds(); | 159 gfx::Rect contents_rect = GetContentsBounds(); |
| 161 int top = contents_rect.y(); | 160 int top = contents_rect.y(); |
| 162 for (int i = 0; i < child_count(); ++i) { | 161 for (int i = 0; i < child_count(); ++i) { |
| 163 View* v = child_at(i); | 162 View* v = child_at(i); |
| 164 if (v->visible()) { | 163 if (v->visible()) { |
| 165 v->SetBounds(contents_rect.x(), top, contents_rect.width(), | 164 v->SetBounds(contents_rect.x(), top, contents_rect.width(), |
| 166 v->GetPreferredSize().height()); | 165 v->GetPreferredSize().height()); |
| 167 top = v->bounds().bottom(); | 166 top = v->bounds().bottom(); |
| 168 } | 167 } |
| 169 } | 168 } |
| 170 } | 169 } |
| 171 | 170 |
| 172 //////////////////////////////////////////////////////////////////////////////// | 171 //////////////////////////////////////////////////////////////////////////////// |
| 173 // AutocompletePopupContentsView, AutocompletePopupView overrides: | 172 // OmniboxPopupContentsView, AutocompletePopupView overrides: |
| 174 | 173 |
| 175 bool AutocompletePopupContentsView::IsOpen() const { | 174 bool OmniboxPopupContentsView::IsOpen() const { |
| 176 return (popup_ != NULL); | 175 return popup_ != NULL; |
| 177 } | 176 } |
| 178 | 177 |
| 179 void AutocompletePopupContentsView::InvalidateLine(size_t line) { | 178 void OmniboxPopupContentsView::InvalidateLine(size_t line) { |
| 180 AutocompleteResultView* result = static_cast<AutocompleteResultView*>( | 179 OmniboxResultView* result = static_cast<OmniboxResultView*>( |
| 181 child_at(static_cast<int>(line))); | 180 child_at(static_cast<int>(line))); |
| 182 result->Invalidate(); | 181 result->Invalidate(); |
| 183 | 182 |
| 184 if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) { | 183 if (HasMatchAt(line) && GetMatchAtIndex(line).associated_keyword.get()) { |
| 185 result->ShowKeyword(IsSelectedIndex(line) && | 184 result->ShowKeyword(IsSelectedIndex(line) && |
| 186 model_->selected_line_state() == AutocompletePopupModel::KEYWORD); | 185 model_->selected_line_state() == AutocompletePopupModel::KEYWORD); |
| 187 } | 186 } |
| 188 } | 187 } |
| 189 | 188 |
| 190 void AutocompletePopupContentsView::UpdatePopupAppearance() { | 189 void OmniboxPopupContentsView::UpdatePopupAppearance() { |
| 191 if (model_->result().empty()) { | 190 if (model_->result().empty()) { |
| 192 // No matches, close any existing popup. | 191 // No matches, close any existing popup. |
| 193 if (popup_ != NULL) { | 192 if (popup_ != NULL) { |
| 194 size_animation_.Stop(); | 193 size_animation_.Stop(); |
| 195 | 194 |
| 196 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack | 195 // NOTE: Do NOT use CloseNow() here, as we may be deep in a callstack |
| 197 // triggered by the popup receiving a message (e.g. LBUTTONUP), and | 196 // triggered by the popup receiving a message (e.g. LBUTTONUP), and |
| 198 // destroying the popup would cause us to read garbage when we unwind back | 197 // destroying the popup would cause us to read garbage when we unwind back |
| 199 // to that level. | 198 // to that level. |
| 200 popup_->Close(); // This will eventually delete the popup. | 199 popup_->Close(); // This will eventually delete the popup. |
| 201 popup_.reset(); | 200 popup_.reset(); |
| 202 } | 201 } |
| 203 return; | 202 return; |
| 204 } | 203 } |
| 205 | 204 |
| 206 // Update the match cached by each row, in the process of doing so make sure | 205 // Update the match cached by each row, in the process of doing so make sure |
| 207 // we have enough row views. | 206 // we have enough row views. |
| 208 size_t child_rv_count = child_count(); | 207 size_t child_rv_count = child_count(); |
| 209 const size_t result_size = model_->result().size(); | 208 const size_t result_size = model_->result().size(); |
| 210 for (size_t i = 0; i < result_size; ++i) { | 209 for (size_t i = 0; i < result_size; ++i) { |
| 211 AutocompleteResultView* view = static_cast<AutocompleteResultView*>( | 210 OmniboxResultView* view = static_cast<OmniboxResultView*>( |
|
Peter Kasting
2012/06/18 19:24:09
Nit: This will now fit on one line.
| |
| 212 child_at(i)); | 211 child_at(i)); |
| 213 view->SetMatch(GetMatchAtIndex(i)); | 212 view->SetMatch(GetMatchAtIndex(i)); |
| 214 view->SetVisible(true); | 213 view->SetVisible(true); |
| 215 } | 214 } |
| 216 for (size_t i = result_size; i < child_rv_count; ++i) | 215 for (size_t i = result_size; i < child_rv_count; ++i) |
| 217 child_at(i)->SetVisible(false); | 216 child_at(i)->SetVisible(false); |
| 218 | 217 |
| 219 gfx::Rect new_target_bounds = CalculateTargetBounds(CalculatePopupHeight()); | 218 gfx::Rect new_target_bounds = CalculateTargetBounds(CalculatePopupHeight()); |
| 220 | 219 |
| 221 // If we're animating and our target height changes, reset the animation. | 220 // If we're animating and our target height changes, reset the animation. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 if (target_bounds_.height() < start_bounds_.height()) | 259 if (target_bounds_.height() < start_bounds_.height()) |
| 261 size_animation_.Show(); | 260 size_animation_.Show(); |
| 262 else | 261 else |
| 263 start_bounds_ = target_bounds_; | 262 start_bounds_ = target_bounds_; |
| 264 popup_->SetBounds(GetPopupBounds()); | 263 popup_->SetBounds(GetPopupBounds()); |
| 265 } | 264 } |
| 266 | 265 |
| 267 SchedulePaint(); | 266 SchedulePaint(); |
| 268 } | 267 } |
| 269 | 268 |
| 270 gfx::Rect AutocompletePopupContentsView::GetTargetBounds() { | 269 gfx::Rect OmniboxPopupContentsView::GetTargetBounds() { |
| 271 return target_bounds_; | 270 return target_bounds_; |
| 272 } | 271 } |
| 273 | 272 |
| 274 void AutocompletePopupContentsView::PaintUpdatesNow() { | 273 void OmniboxPopupContentsView::PaintUpdatesNow() { |
| 275 // TODO(beng): remove this from the interface. | 274 // TODO(beng): remove this from the interface. |
| 276 } | 275 } |
| 277 | 276 |
| 278 void AutocompletePopupContentsView::OnDragCanceled() { | 277 void OmniboxPopupContentsView::OnDragCanceled() { |
| 279 ignore_mouse_drag_ = true; | 278 ignore_mouse_drag_ = true; |
| 280 } | 279 } |
| 281 | 280 |
| 282 //////////////////////////////////////////////////////////////////////////////// | 281 //////////////////////////////////////////////////////////////////////////////// |
| 283 // AutocompletePopupContentsView, AutocompleteResultViewModel implementation: | 282 // OmniboxPopupContentsView, OmniboxResultViewModel implementation: |
| 284 | 283 |
| 285 bool AutocompletePopupContentsView::IsSelectedIndex(size_t index) const { | 284 bool OmniboxPopupContentsView::IsSelectedIndex(size_t index) const { |
| 286 return index == model_->selected_line(); | 285 return index == model_->selected_line(); |
| 287 } | 286 } |
| 288 | 287 |
| 289 bool AutocompletePopupContentsView::IsHoveredIndex(size_t index) const { | 288 bool OmniboxPopupContentsView::IsHoveredIndex(size_t index) const { |
| 290 return index == model_->hovered_line(); | 289 return index == model_->hovered_line(); |
| 291 } | 290 } |
| 292 | 291 |
| 293 const SkBitmap* AutocompletePopupContentsView::GetIconIfExtensionMatch( | 292 const SkBitmap* OmniboxPopupContentsView::GetIconIfExtensionMatch( |
| 294 size_t index) const { | 293 size_t index) const { |
| 295 if (!HasMatchAt(index)) | 294 if (!HasMatchAt(index)) |
| 296 return NULL; | 295 return NULL; |
| 297 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); | 296 return model_->GetIconIfExtensionMatch(GetMatchAtIndex(index)); |
| 298 } | 297 } |
| 299 | 298 |
| 300 //////////////////////////////////////////////////////////////////////////////// | 299 //////////////////////////////////////////////////////////////////////////////// |
| 301 // AutocompletePopupContentsView, AnimationDelegate implementation: | 300 // OmniboxPopupContentsView, AnimationDelegate implementation: |
| 302 | 301 |
| 303 void AutocompletePopupContentsView::AnimationProgressed( | 302 void OmniboxPopupContentsView::AnimationProgressed( |
| 304 const ui::Animation* animation) { | 303 const ui::Animation* animation) { |
| 305 // We should only be running the animation when the popup is already visible. | 304 // We should only be running the animation when the popup is already visible. |
| 306 DCHECK(popup_ != NULL); | 305 DCHECK(popup_ != NULL); |
| 307 popup_->SetBounds(GetPopupBounds()); | 306 popup_->SetBounds(GetPopupBounds()); |
| 308 } | 307 } |
| 309 | 308 |
| 310 //////////////////////////////////////////////////////////////////////////////// | 309 //////////////////////////////////////////////////////////////////////////////// |
| 311 // AutocompletePopupContentsView, views::View overrides: | 310 // OmniboxPopupContentsView, views::View overrides: |
| 312 | 311 |
| 313 void AutocompletePopupContentsView::Layout() { | 312 void OmniboxPopupContentsView::Layout() { |
| 314 UpdateBlurRegion(); | 313 UpdateBlurRegion(); |
| 315 | 314 |
| 316 // Size our children to the available content area. | 315 // Size our children to the available content area. |
| 317 LayoutChildren(); | 316 LayoutChildren(); |
| 318 | 317 |
| 319 // We need to manually schedule a paint here since we are a layered window and | 318 // We need to manually schedule a paint here since we are a layered window and |
| 320 // won't implicitly require painting until we ask for one. | 319 // won't implicitly require painting until we ask for one. |
| 321 SchedulePaint(); | 320 SchedulePaint(); |
| 322 } | 321 } |
| 323 | 322 |
| 324 views::View* AutocompletePopupContentsView::GetEventHandlerForPoint( | 323 views::View* OmniboxPopupContentsView::GetEventHandlerForPoint( |
| 325 const gfx::Point& point) { | 324 const gfx::Point& point) { |
| 326 return this; | 325 return this; |
| 327 } | 326 } |
| 328 | 327 |
| 329 bool AutocompletePopupContentsView::OnMousePressed( | 328 bool OmniboxPopupContentsView::OnMousePressed( |
| 330 const views::MouseEvent& event) { | 329 const views::MouseEvent& event) { |
| 331 ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header. | 330 ignore_mouse_drag_ = false; // See comment on |ignore_mouse_drag_| in header. |
| 332 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) | 331 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) |
| 333 UpdateLineEvent(event, event.IsLeftMouseButton()); | 332 UpdateLineEvent(event, event.IsLeftMouseButton()); |
| 334 return true; | 333 return true; |
| 335 } | 334 } |
| 336 | 335 |
| 337 bool AutocompletePopupContentsView::OnMouseDragged( | 336 bool OmniboxPopupContentsView::OnMouseDragged( |
| 338 const views::MouseEvent& event) { | 337 const views::MouseEvent& event) { |
| 339 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) | 338 if (event.IsLeftMouseButton() || event.IsMiddleMouseButton()) |
| 340 UpdateLineEvent(event, !ignore_mouse_drag_ && event.IsLeftMouseButton()); | 339 UpdateLineEvent(event, !ignore_mouse_drag_ && event.IsLeftMouseButton()); |
| 341 return true; | 340 return true; |
| 342 } | 341 } |
| 343 | 342 |
| 344 void AutocompletePopupContentsView::OnMouseReleased( | 343 void OmniboxPopupContentsView::OnMouseReleased( |
| 345 const views::MouseEvent& event) { | 344 const views::MouseEvent& event) { |
| 346 if (ignore_mouse_drag_) { | 345 if (ignore_mouse_drag_) { |
| 347 OnMouseCaptureLost(); | 346 OnMouseCaptureLost(); |
| 348 return; | 347 return; |
| 349 } | 348 } |
| 350 | 349 |
| 351 if (event.IsOnlyMiddleMouseButton() || event.IsOnlyLeftMouseButton()) { | 350 if (event.IsOnlyMiddleMouseButton() || event.IsOnlyLeftMouseButton()) { |
| 352 OpenSelectedLine(event, event.IsOnlyLeftMouseButton() ? CURRENT_TAB : | 351 OpenSelectedLine(event, event.IsOnlyLeftMouseButton() ? CURRENT_TAB : |
| 353 NEW_BACKGROUND_TAB); | 352 NEW_BACKGROUND_TAB); |
| 354 } | 353 } |
| 355 } | 354 } |
| 356 | 355 |
| 357 void AutocompletePopupContentsView::OnMouseCaptureLost() { | 356 void OmniboxPopupContentsView::OnMouseCaptureLost() { |
| 358 ignore_mouse_drag_ = false; | 357 ignore_mouse_drag_ = false; |
| 359 } | 358 } |
| 360 | 359 |
| 361 void AutocompletePopupContentsView::OnMouseMoved( | 360 void OmniboxPopupContentsView::OnMouseMoved( |
| 362 const views::MouseEvent& event) { | 361 const views::MouseEvent& event) { |
| 363 model_->SetHoveredLine(GetIndexForPoint(event.location())); | 362 model_->SetHoveredLine(GetIndexForPoint(event.location())); |
| 364 } | 363 } |
| 365 | 364 |
| 366 void AutocompletePopupContentsView::OnMouseEntered( | 365 void OmniboxPopupContentsView::OnMouseEntered( |
| 367 const views::MouseEvent& event) { | 366 const views::MouseEvent& event) { |
| 368 model_->SetHoveredLine(GetIndexForPoint(event.location())); | 367 model_->SetHoveredLine(GetIndexForPoint(event.location())); |
| 369 } | 368 } |
| 370 | 369 |
| 371 void AutocompletePopupContentsView::OnMouseExited( | 370 void OmniboxPopupContentsView::OnMouseExited( |
| 372 const views::MouseEvent& event) { | 371 const views::MouseEvent& event) { |
| 373 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); | 372 model_->SetHoveredLine(AutocompletePopupModel::kNoMatch); |
| 374 } | 373 } |
| 375 | 374 |
| 376 ui::GestureStatus AutocompletePopupContentsView::OnGestureEvent( | 375 ui::GestureStatus OmniboxPopupContentsView::OnGestureEvent( |
| 377 const views::GestureEvent& event) { | 376 const views::GestureEvent& event) { |
| 378 switch (event.type()) { | 377 switch (event.type()) { |
| 379 case ui::ET_GESTURE_TAP_DOWN: | 378 case ui::ET_GESTURE_TAP_DOWN: |
| 380 case ui::ET_GESTURE_SCROLL_BEGIN: | 379 case ui::ET_GESTURE_SCROLL_BEGIN: |
| 381 case ui::ET_GESTURE_SCROLL_UPDATE: | 380 case ui::ET_GESTURE_SCROLL_UPDATE: |
| 382 UpdateLineEvent(event, true); | 381 UpdateLineEvent(event, true); |
| 383 break; | 382 break; |
| 384 case ui::ET_GESTURE_TAP: | 383 case ui::ET_GESTURE_TAP: |
| 385 case ui::ET_GESTURE_SCROLL_END: | 384 case ui::ET_GESTURE_SCROLL_END: |
| 386 OpenSelectedLine(event, CURRENT_TAB); | 385 OpenSelectedLine(event, CURRENT_TAB); |
| 387 break; | 386 break; |
| 388 default: | 387 default: |
| 389 return ui::GESTURE_STATUS_UNKNOWN; | 388 return ui::GESTURE_STATUS_UNKNOWN; |
| 390 } | 389 } |
| 391 return ui::GESTURE_STATUS_CONSUMED; | 390 return ui::GESTURE_STATUS_CONSUMED; |
| 392 } | 391 } |
| 393 | 392 |
| 394 //////////////////////////////////////////////////////////////////////////////// | 393 //////////////////////////////////////////////////////////////////////////////// |
| 395 // AutocompletePopupContentsView, protected: | 394 // OmniboxPopupContentsView, protected: |
| 396 | 395 |
| 397 void AutocompletePopupContentsView::PaintResultViews(gfx::Canvas* canvas) { | 396 void OmniboxPopupContentsView::PaintResultViews(gfx::Canvas* canvas) { |
| 398 canvas->DrawColor(AutocompleteResultView::GetColor( | 397 canvas->DrawColor(OmniboxResultView::GetColor( |
| 399 AutocompleteResultView::NORMAL, AutocompleteResultView::BACKGROUND)); | 398 OmniboxResultView::NORMAL, OmniboxResultView::BACKGROUND)); |
| 400 View::PaintChildren(canvas); | 399 View::PaintChildren(canvas); |
| 401 } | 400 } |
| 402 | 401 |
| 403 int AutocompletePopupContentsView::CalculatePopupHeight() { | 402 int OmniboxPopupContentsView::CalculatePopupHeight() { |
| 404 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); | 403 DCHECK_GE(static_cast<size_t>(child_count()), model_->result().size()); |
| 405 int popup_height = 0; | 404 int popup_height = 0; |
| 406 for (size_t i = 0; i < model_->result().size(); ++i) | 405 for (size_t i = 0; i < model_->result().size(); ++i) |
| 407 popup_height += child_at(i)->GetPreferredSize().height(); | 406 popup_height += child_at(i)->GetPreferredSize().height(); |
| 408 return popup_height; | 407 return popup_height; |
| 409 } | 408 } |
| 410 | 409 |
| 411 AutocompleteResultView* AutocompletePopupContentsView::CreateResultView( | 410 OmniboxResultView* OmniboxPopupContentsView::CreateResultView( |
| 412 AutocompleteResultViewModel* model, | 411 OmniboxResultViewModel* model, |
| 413 int model_index, | 412 int model_index, |
| 414 const gfx::Font& font, | 413 const gfx::Font& font, |
| 415 const gfx::Font& bold_font) { | 414 const gfx::Font& bold_font) { |
| 416 return new AutocompleteResultView(model, model_index, font, bold_font); | 415 return new OmniboxResultView(model, model_index, font, bold_font); |
| 417 } | 416 } |
| 418 | 417 |
| 419 //////////////////////////////////////////////////////////////////////////////// | 418 //////////////////////////////////////////////////////////////////////////////// |
| 420 // AutocompletePopupContentsView, views::View overrides, protected: | 419 // OmniboxPopupContentsView, views::View overrides, protected: |
| 421 | 420 |
| 422 void AutocompletePopupContentsView::OnPaint(gfx::Canvas* canvas) { | 421 void OmniboxPopupContentsView::OnPaint(gfx::Canvas* canvas) { |
| 423 gfx::Path path; | 422 gfx::Path path; |
| 424 MakeContentsPath(&path, GetContentsBounds()); | 423 MakeContentsPath(&path, GetContentsBounds()); |
| 425 canvas->Save(); | 424 canvas->Save(); |
| 426 canvas->sk_canvas()->clipPath(path, | 425 canvas->sk_canvas()->clipPath(path, |
| 427 SkRegion::kIntersect_Op, | 426 SkRegion::kIntersect_Op, |
| 428 true /* doAntialias */); | 427 true /* doAntialias */); |
| 429 PaintResultViews(canvas); | 428 PaintResultViews(canvas); |
| 430 | 429 |
| 431 // We want the contents background to be slightly transparent so we can see | 430 // We want the contents background to be slightly transparent so we can see |
| 432 // the blurry glass effect on DWM systems behind. We do this _after_ we paint | 431 // the blurry glass effect on DWM systems behind. We do this _after_ we paint |
| 433 // the children since they paint text, and GDI will reset this alpha data if | 432 // the children since they paint text, and GDI will reset this alpha data if |
| 434 // we paint text after this call. | 433 // we paint text after this call. |
| 435 MakeCanvasTransparent(canvas); | 434 MakeCanvasTransparent(canvas); |
| 436 canvas->Restore(); | 435 canvas->Restore(); |
| 437 | 436 |
| 438 // Now we paint the border, so it will be alpha-blended atop the contents. | 437 // Now we paint the border, so it will be alpha-blended atop the contents. |
| 439 // This looks slightly better in the corners than drawing the contents atop | 438 // This looks slightly better in the corners than drawing the contents atop |
| 440 // the border. | 439 // the border. |
| 441 OnPaintBorder(canvas); | 440 OnPaintBorder(canvas); |
| 442 } | 441 } |
| 443 | 442 |
| 444 void AutocompletePopupContentsView::PaintChildren(gfx::Canvas* canvas) { | 443 void OmniboxPopupContentsView::PaintChildren(gfx::Canvas* canvas) { |
| 445 // We paint our children inside OnPaint(). | 444 // We paint our children inside OnPaint(). |
| 446 } | 445 } |
| 447 | 446 |
| 448 //////////////////////////////////////////////////////////////////////////////// | 447 //////////////////////////////////////////////////////////////////////////////// |
| 449 // AutocompletePopupContentsView, private: | 448 // OmniboxPopupContentsView, private: |
| 450 | 449 |
| 451 bool AutocompletePopupContentsView::HasMatchAt(size_t index) const { | 450 bool OmniboxPopupContentsView::HasMatchAt(size_t index) const { |
| 452 return index < model_->result().size(); | 451 return index < model_->result().size(); |
| 453 } | 452 } |
| 454 | 453 |
| 455 const AutocompleteMatch& AutocompletePopupContentsView::GetMatchAtIndex( | 454 const AutocompleteMatch& OmniboxPopupContentsView::GetMatchAtIndex( |
| 456 size_t index) const { | 455 size_t index) const { |
| 457 return model_->result().match_at(index); | 456 return model_->result().match_at(index); |
| 458 } | 457 } |
| 459 | 458 |
| 460 void AutocompletePopupContentsView::MakeContentsPath( | 459 void OmniboxPopupContentsView::MakeContentsPath( |
| 461 gfx::Path* path, | 460 gfx::Path* path, |
| 462 const gfx::Rect& bounding_rect) { | 461 const gfx::Rect& bounding_rect) { |
| 463 SkRect rect; | 462 SkRect rect; |
| 464 rect.set(SkIntToScalar(bounding_rect.x()), | 463 rect.set(SkIntToScalar(bounding_rect.x()), |
| 465 SkIntToScalar(bounding_rect.y()), | 464 SkIntToScalar(bounding_rect.y()), |
| 466 SkIntToScalar(bounding_rect.right()), | 465 SkIntToScalar(bounding_rect.right()), |
| 467 SkIntToScalar(bounding_rect.bottom())); | 466 SkIntToScalar(bounding_rect.bottom())); |
| 468 | 467 |
| 469 SkScalar radius = SkIntToScalar(views::BubbleBorder::GetCornerRadius()); | 468 SkScalar radius = SkIntToScalar(views::BubbleBorder::GetCornerRadius()); |
| 470 path->addRoundRect(rect, radius, radius); | 469 path->addRoundRect(rect, radius, radius); |
| 471 } | 470 } |
| 472 | 471 |
| 473 void AutocompletePopupContentsView::UpdateBlurRegion() { | 472 void OmniboxPopupContentsView::UpdateBlurRegion() { |
| 474 #if defined(OS_WIN) && !defined(USE_AURA) | 473 #if defined(OS_WIN) && !defined(USE_AURA) |
| 475 // We only support background blurring on Vista with Aero-Glass enabled. | 474 // We only support background blurring on Vista with Aero-Glass enabled. |
| 476 if (!views::NativeWidgetWin::IsAeroGlassEnabled() || !GetWidget()) | 475 if (!views::NativeWidgetWin::IsAeroGlassEnabled() || !GetWidget()) |
| 477 return; | 476 return; |
| 478 | 477 |
| 479 // Provide a blurred background effect within the contents region of the | 478 // Provide a blurred background effect within the contents region of the |
| 480 // popup. | 479 // popup. |
| 481 DWM_BLURBEHIND bb = {0}; | 480 DWM_BLURBEHIND bb = {0}; |
| 482 bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; | 481 bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; |
| 483 bb.fEnable = true; | 482 bb.fEnable = true; |
| 484 | 483 |
| 485 // Translate the contents rect into widget coordinates, since that's what | 484 // Translate the contents rect into widget coordinates, since that's what |
| 486 // DwmEnableBlurBehindWindow expects a region in. | 485 // DwmEnableBlurBehindWindow expects a region in. |
| 487 gfx::Rect contents_rect = ConvertRectToWidget(GetContentsBounds()); | 486 gfx::Rect contents_rect = ConvertRectToWidget(GetContentsBounds()); |
| 488 gfx::Path contents_path; | 487 gfx::Path contents_path; |
| 489 MakeContentsPath(&contents_path, contents_rect); | 488 MakeContentsPath(&contents_path, contents_rect); |
| 490 base::win::ScopedGDIObject<HRGN> popup_region; | 489 base::win::ScopedGDIObject<HRGN> popup_region; |
| 491 popup_region.Set(contents_path.CreateNativeRegion()); | 490 popup_region.Set(contents_path.CreateNativeRegion()); |
| 492 bb.hRgnBlur = popup_region.Get(); | 491 bb.hRgnBlur = popup_region.Get(); |
| 493 DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb); | 492 DwmEnableBlurBehindWindow(GetWidget()->GetNativeView(), &bb); |
| 494 #endif | 493 #endif |
| 495 } | 494 } |
| 496 | 495 |
| 497 void AutocompletePopupContentsView::MakeCanvasTransparent( | 496 void OmniboxPopupContentsView::MakeCanvasTransparent(gfx::Canvas* canvas) { |
| 498 gfx::Canvas* canvas) { | |
| 499 // Allow the window blur effect to show through the popup background. | 497 // Allow the window blur effect to show through the popup background. |
| 500 SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ? | 498 SkAlpha alpha = GetThemeProvider()->ShouldUseNativeFrame() ? |
| 501 kGlassPopupAlpha : kOpaquePopupAlpha; | 499 kGlassPopupAlpha : kOpaquePopupAlpha; |
| 502 canvas->DrawColor(SkColorSetA( | 500 canvas->DrawColor(SkColorSetA( |
| 503 AutocompleteResultView::GetColor(AutocompleteResultView::NORMAL, | 501 OmniboxResultView::GetColor(OmniboxResultView::NORMAL, |
| 504 AutocompleteResultView::BACKGROUND), alpha), SkXfermode::kDstIn_Mode); | 502 OmniboxResultView::BACKGROUND), alpha), SkXfermode::kDstIn_Mode); |
|
Peter Kasting
2012/06/18 19:24:09
Nit: Indent 4 more
| |
| 505 } | 503 } |
| 506 | 504 |
| 507 void AutocompletePopupContentsView::OpenIndex( | 505 void OmniboxPopupContentsView::OpenIndex(size_t index, |
| 508 size_t index, | 506 WindowOpenDisposition disposition) { |
| 509 WindowOpenDisposition disposition) { | |
| 510 if (!HasMatchAt(index)) | 507 if (!HasMatchAt(index)) |
| 511 return; | 508 return; |
| 512 | 509 |
| 513 // OpenMatch() may close the popup, which will clear the result set and, by | 510 // OpenMatch() may close the popup, which will clear the result set and, by |
| 514 // extension, |match| and its contents. So copy the relevant match out to | 511 // extension, |match| and its contents. So copy the relevant match out to |
| 515 // make sure it stays alive until the call completes. | 512 // make sure it stays alive until the call completes. |
| 516 AutocompleteMatch match = model_->result().match_at(index); | 513 AutocompleteMatch match = model_->result().match_at(index); |
| 517 omnibox_view_->OpenMatch(match, disposition, GURL(), index); | 514 omnibox_view_->OpenMatch(match, disposition, GURL(), index); |
| 518 } | 515 } |
| 519 | 516 |
| 520 size_t AutocompletePopupContentsView::GetIndexForPoint( | 517 size_t OmniboxPopupContentsView::GetIndexForPoint( |
| 521 const gfx::Point& point) { | 518 const gfx::Point& point) { |
| 522 if (!HitTest(point)) | 519 if (!HitTest(point)) |
| 523 return AutocompletePopupModel::kNoMatch; | 520 return AutocompletePopupModel::kNoMatch; |
| 524 | 521 |
| 525 int nb_match = model_->result().size(); | 522 int nb_match = model_->result().size(); |
| 526 DCHECK(nb_match <= child_count()); | 523 DCHECK(nb_match <= child_count()); |
| 527 for (int i = 0; i < nb_match; ++i) { | 524 for (int i = 0; i < nb_match; ++i) { |
| 528 views::View* child = child_at(i); | 525 views::View* child = child_at(i); |
| 529 gfx::Point point_in_child_coords(point); | 526 gfx::Point point_in_child_coords(point); |
| 530 View::ConvertPointToView(this, child, &point_in_child_coords); | 527 View::ConvertPointToView(this, child, &point_in_child_coords); |
| 531 if (child->HitTest(point_in_child_coords)) | 528 if (child->HitTest(point_in_child_coords)) |
| 532 return i; | 529 return i; |
| 533 } | 530 } |
| 534 return AutocompletePopupModel::kNoMatch; | 531 return AutocompletePopupModel::kNoMatch; |
| 535 } | 532 } |
| 536 | 533 |
| 537 gfx::Rect AutocompletePopupContentsView::CalculateTargetBounds(int h) { | 534 gfx::Rect OmniboxPopupContentsView::CalculateTargetBounds(int h) { |
| 538 gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds()); | 535 gfx::Rect location_bar_bounds(location_bar_->GetContentsBounds()); |
| 539 const views::Border* border = location_bar_->border(); | 536 const views::Border* border = location_bar_->border(); |
| 540 if (border) { | 537 if (border) { |
| 541 // Adjust for the border so that the bubble and location bar borders are | 538 // Adjust for the border so that the bubble and location bar borders are |
| 542 // aligned. | 539 // aligned. |
| 543 gfx::Insets insets; | 540 gfx::Insets insets; |
| 544 border->GetInsets(&insets); | 541 border->GetInsets(&insets); |
| 545 location_bar_bounds.Inset(insets.left(), 0, insets.right(), 0); | 542 location_bar_bounds.Inset(insets.left(), 0, insets.right(), 0); |
| 546 } else { | 543 } else { |
| 547 // The normal location bar is drawn using a background graphic that includes | 544 // The normal location bar is drawn using a background graphic that includes |
| 548 // the border, so we inset by enough to make the edges line up, and the | 545 // the border, so we inset by enough to make the edges line up, and the |
| 549 // bubble appear at the same height as the Star bubble. | 546 // bubble appear at the same height as the Star bubble. |
| 550 location_bar_bounds.Inset(LocationBarView::kNormalHorizontalEdgeThickness, | 547 location_bar_bounds.Inset(LocationBarView::kNormalHorizontalEdgeThickness, |
| 551 0); | 548 0); |
| 552 } | 549 } |
| 553 gfx::Point location_bar_origin(location_bar_bounds.origin()); | 550 gfx::Point location_bar_origin(location_bar_bounds.origin()); |
| 554 views::View::ConvertPointToScreen(location_bar_, &location_bar_origin); | 551 views::View::ConvertPointToScreen(location_bar_, &location_bar_origin); |
| 555 location_bar_bounds.set_origin(location_bar_origin); | 552 location_bar_bounds.set_origin(location_bar_origin); |
| 556 return bubble_border_->GetBounds( | 553 return bubble_border_->GetBounds( |
| 557 location_bar_bounds, gfx::Size(location_bar_bounds.width(), h)); | 554 location_bar_bounds, gfx::Size(location_bar_bounds.width(), h)); |
| 558 } | 555 } |
| 559 | 556 |
| 560 void AutocompletePopupContentsView::UpdateLineEvent( | 557 void OmniboxPopupContentsView::UpdateLineEvent( |
| 561 const views::LocatedEvent& event, | 558 const views::LocatedEvent& event, |
| 562 bool should_set_selected_line) { | 559 bool should_set_selected_line) { |
| 563 size_t index = GetIndexForPoint(event.location()); | 560 size_t index = GetIndexForPoint(event.location()); |
| 564 model_->SetHoveredLine(index); | 561 model_->SetHoveredLine(index); |
| 565 if (HasMatchAt(index) && should_set_selected_line) | 562 if (HasMatchAt(index) && should_set_selected_line) |
| 566 model_->SetSelectedLine(index, false, false); | 563 model_->SetSelectedLine(index, false, false); |
| 567 } | 564 } |
| 568 | 565 |
| 569 void AutocompletePopupContentsView::OpenSelectedLine( | 566 void OmniboxPopupContentsView::OpenSelectedLine( |
| 570 const views::LocatedEvent& event, | 567 const views::LocatedEvent& event, |
| 571 WindowOpenDisposition disposition) { | 568 WindowOpenDisposition disposition) { |
| 572 size_t index = GetIndexForPoint(event.location()); | 569 size_t index = GetIndexForPoint(event.location()); |
| 573 OpenIndex(index, disposition); | 570 OpenIndex(index, disposition); |
| 574 } | 571 } |
| OLD | NEW |