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/infobars/infobar_view.h" | 5 #include "chrome/browser/ui/views/infobars/infobar_view.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 | 61 |
62 InfoBarView::InfoBarView(TabContentsWrapper* owner, InfoBarDelegate* delegate) | 62 InfoBarView::InfoBarView(TabContentsWrapper* owner, InfoBarDelegate* delegate) |
63 : InfoBar(owner, delegate), | 63 : InfoBar(owner, delegate), |
64 icon_(NULL), | 64 icon_(NULL), |
65 close_button_(NULL) { | 65 close_button_(NULL) { |
66 set_parent_owned(false); // InfoBar deletes itself at the appropriate time. | 66 set_parent_owned(false); // InfoBar deletes itself at the appropriate time. |
67 set_background(new InfoBarBackground(delegate->GetInfoBarType())); | 67 set_background(new InfoBarBackground(delegate->GetInfoBarType())); |
68 } | 68 } |
69 | 69 |
70 InfoBarView::~InfoBarView() { | 70 InfoBarView::~InfoBarView() { |
| 71 // We should have closed any open menus in PlatformSpecificHide(), then |
| 72 // subclasses' RunMenu() functions should have prevented opening any new ones |
| 73 // once we became unowned. |
| 74 DCHECK(!menu_runner_.get()); |
71 } | 75 } |
72 | 76 |
73 // static | 77 // static |
74 views::Label* InfoBarView::CreateLabel(const string16& text) { | 78 views::Label* InfoBarView::CreateLabel(const string16& text) { |
75 views::Label* label = new views::Label(UTF16ToWideHack(text), | 79 views::Label* label = new views::Label(UTF16ToWideHack(text), |
76 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont)); | 80 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont)); |
77 label->SetColor(SK_ColorBLACK); | 81 label->SetColor(SK_ColorBLACK); |
78 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); | 82 label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); |
79 return label; | 83 return label; |
80 } | 84 } |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // canvas_skia->clipPath(fill_path_); | 256 // canvas_skia->clipPath(fill_path_); |
253 DCHECK_EQ(total_height(), height()) | 257 DCHECK_EQ(total_height(), height()) |
254 << "Infobar piecewise heights do not match overall height"; | 258 << "Infobar piecewise heights do not match overall height"; |
255 canvas->ClipRectInt(0, arrow_height(), width(), bar_height()); | 259 canvas->ClipRectInt(0, arrow_height(), width(), bar_height()); |
256 views::View::PaintChildren(canvas); | 260 views::View::PaintChildren(canvas); |
257 canvas->Restore(); | 261 canvas->Restore(); |
258 } | 262 } |
259 | 263 |
260 void InfoBarView::ButtonPressed(views::Button* sender, | 264 void InfoBarView::ButtonPressed(views::Button* sender, |
261 const views::Event& event) { | 265 const views::Event& event) { |
| 266 DCHECK(owned()); // Subclasses should never call us while we're closing. |
262 if (sender == close_button_) { | 267 if (sender == close_button_) { |
263 // If we're not owned, we're already closing, so don't call | 268 delegate()->InfoBarDismissed(); |
264 // InfoBarDismissed(), since this can lead to us double-recording | |
265 // dismissals. | |
266 if (delegate() && owned()) | |
267 delegate()->InfoBarDismissed(); | |
268 RemoveSelf(); | 269 RemoveSelf(); |
269 } | 270 } |
270 } | 271 } |
271 | 272 |
272 int InfoBarView::ContentMinimumWidth() const { | 273 int InfoBarView::ContentMinimumWidth() const { |
273 return 0; | 274 return 0; |
274 } | 275 } |
275 | 276 |
276 int InfoBarView::StartX() const { | 277 int InfoBarView::StartX() const { |
277 // Ensure we don't return a value greater than EndX(), so children can safely | 278 // Ensure we don't return a value greater than EndX(), so children can safely |
278 // set something's width to "EndX() - StartX()" without risking that being | 279 // set something's width to "EndX() - StartX()" without risking that being |
279 // negative. | 280 // negative. |
280 return std::min(EndX(), | 281 return std::min(EndX(), |
281 ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding); | 282 ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding); |
282 } | 283 } |
283 | 284 |
284 int InfoBarView::EndX() const { | 285 int InfoBarView::EndX() const { |
285 const int kCloseButtonSpacing = 12; | 286 const int kCloseButtonSpacing = 12; |
286 return close_button_->x() - kCloseButtonSpacing; | 287 return close_button_->x() - kCloseButtonSpacing; |
287 } | 288 } |
288 | 289 |
289 const InfoBarContainer::Delegate* InfoBarView::container_delegate() const { | 290 const InfoBarContainer::Delegate* InfoBarView::container_delegate() const { |
290 const InfoBarContainer* infobar_container = container(); | 291 const InfoBarContainer* infobar_container = container(); |
291 return infobar_container ? infobar_container->delegate() : NULL; | 292 return infobar_container ? infobar_container->delegate() : NULL; |
292 } | 293 } |
293 | 294 |
294 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model, | 295 void InfoBarView::RunMenuAt(ui::MenuModel* menu_model, |
295 views::MenuButton* button, | 296 views::MenuButton* button, |
296 views::MenuItemView::AnchorPosition anchor) { | 297 views::MenuItemView::AnchorPosition anchor) { |
| 298 DCHECK(owned()); // We'd better not open any menus while we're closing. |
297 views::MenuModelAdapter adapter(menu_model); | 299 views::MenuModelAdapter adapter(menu_model); |
298 gfx::Point screen_point; | 300 gfx::Point screen_point; |
299 views::View::ConvertPointToScreen(button, &screen_point); | 301 views::View::ConvertPointToScreen(button, &screen_point); |
300 menu_runner_.reset(new views::MenuRunner(adapter.CreateMenu())); | 302 menu_runner_.reset(new views::MenuRunner(adapter.CreateMenu())); |
301 // Ignore the result as we know we can only get here after the menu has | 303 // Ignore the result since we don't need to handle a deleted menu specially. |
302 // closed. | |
303 ignore_result(menu_runner_->RunMenuAt( | 304 ignore_result(menu_runner_->RunMenuAt( |
304 GetWidget(), button, gfx::Rect(screen_point, button->size()), anchor, | 305 GetWidget(), button, gfx::Rect(screen_point, button->size()), anchor, |
305 views::MenuRunner::HAS_MNEMONICS)); | 306 views::MenuRunner::HAS_MNEMONICS)); |
306 // TODO(pkasting): this may be deleted after rewrite. | |
307 } | 307 } |
308 | 308 |
309 void InfoBarView::PlatformSpecificShow(bool animate) { | 309 void InfoBarView::PlatformSpecificShow(bool animate) { |
310 views::Widget* widget = GetWidget(); | 310 views::Widget* widget = GetWidget(); |
311 views::FocusManager* focus_manager = GetFocusManager(); | 311 views::FocusManager* focus_manager = GetFocusManager(); |
312 #if defined(OS_WIN) | 312 #if defined(OS_WIN) |
313 // If we gain focus, we want to restore it to the previously-focused element | 313 // If we gain focus, we want to restore it to the previously-focused element |
314 // when we're hidden. So when we're in a Widget, create a focus tracker so | 314 // when we're hidden. So when we're in a Widget, create a focus tracker so |
315 // that if we gain focus we'll know what the previously-focused element was. | 315 // that if we gain focus we'll know what the previously-focused element was. |
316 if (widget) { | 316 if (widget) { |
317 focus_tracker_.reset( | 317 focus_tracker_.reset( |
318 new views::ExternalFocusTracker(this, focus_manager)); | 318 new views::ExternalFocusTracker(this, focus_manager)); |
319 } | 319 } |
320 #endif | 320 #endif |
321 if (focus_manager) | 321 if (focus_manager) |
322 focus_manager->AddFocusChangeListener(this); | 322 focus_manager->AddFocusChangeListener(this); |
323 if (widget) { | 323 if (widget) { |
324 widget->NotifyAccessibilityEvent( | 324 widget->NotifyAccessibilityEvent( |
325 this, ui::AccessibilityTypes::EVENT_ALERT, true); | 325 this, ui::AccessibilityTypes::EVENT_ALERT, true); |
326 } | 326 } |
327 } | 327 } |
328 | 328 |
329 void InfoBarView::PlatformSpecificHide(bool animate) { | 329 void InfoBarView::PlatformSpecificHide(bool animate) { |
330 // We're being removed. Cancel any menus we may have open. Because we are | 330 // Cancel any menus we may have open. It doesn't make sense to leave them |
331 // deleted after a delay and after our delegate is deleted we have to | 331 // open while we're hidden, and if we're going to become unowned, we can't |
332 // explicitly cancel the menu rather than relying on the destructor to cancel | 332 // allow the user to choose any options and potentially call functions that |
333 // the menu. | 333 // try to access the owner. |
334 menu_runner_.reset(); | 334 menu_runner_.reset(); |
335 | 335 |
336 // It's possible to be called twice (once with |animate| true and once with it | 336 // It's possible to be called twice (once with |animate| true and once with it |
337 // false); in this case the second RemoveFocusChangeListener() call will | 337 // false); in this case the second RemoveFocusChangeListener() call will |
338 // silently no-op. | 338 // silently no-op. |
339 views::FocusManager* focus_manager = GetFocusManager(); | 339 views::FocusManager* focus_manager = GetFocusManager(); |
340 if (focus_manager) | 340 if (focus_manager) |
341 focus_manager->RemoveFocusChangeListener(this); | 341 focus_manager->RemoveFocusChangeListener(this); |
342 | 342 |
343 #if defined(OS_WIN) && !defined(USE_AURA) | 343 #if defined(OS_WIN) && !defined(USE_AURA) |
(...skipping 30 matching lines...) Expand all Loading... |
374 | 374 |
375 void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) { | 375 void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) { |
376 // This will trigger some screen readers to read the entire contents of this | 376 // This will trigger some screen readers to read the entire contents of this |
377 // infobar. | 377 // infobar. |
378 if (focused_before && focused_now && !Contains(focused_before) && | 378 if (focused_before && focused_now && !Contains(focused_before) && |
379 Contains(focused_now) && GetWidget()) { | 379 Contains(focused_now) && GetWidget()) { |
380 GetWidget()->NotifyAccessibilityEvent( | 380 GetWidget()->NotifyAccessibilityEvent( |
381 this, ui::AccessibilityTypes::EVENT_ALERT, true); | 381 this, ui::AccessibilityTypes::EVENT_ALERT, true); |
382 } | 382 } |
383 } | 383 } |
OLD | NEW |