diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 19:13:39 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-01 19:13:39 +0000 |
commit | 9cefab614bdf79e902f94bf13075b856e20ddf40 (patch) | |
tree | 3628ca90cf71da7da7a94dd026ca79c3072efa2b /chrome/browser/ui/views | |
parent | 722c251aeebd8a76142352f898903f8a2b5375d9 (diff) | |
download | chromium_src-9cefab614bdf79e902f94bf13075b856e20ddf40.zip chromium_src-9cefab614bdf79e902f94bf13075b856e20ddf40.tar.gz chromium_src-9cefab614bdf79e902f94bf13075b856e20ddf40.tar.bz2 |
Layout changes for InfoBarView and subclasses:
* Lay out ConfirmInfoBar as per current UI guidelines (bug 39102)
* Remove now-unnecessary dedicated autofill infobar, which implemented correct infobar layout only for autofill, since the default ConfirmInfoBar is now correct
* ConfirmInfoBar: Don't create OK/Cancel buttons or link at all when not needed (bug 27832)
* Add child views when the infobar is first made part of the view hierarchy rather than at construction (simplifies ownership, matches standard implementation pattern)
* Translate infobars: Create language menus at construction rather than on demand (simpler code)
* Elide text elements as infobar width shrinks
* ...but, stop layout changes for infobar content when the infobar reaches a minimum width (i.e. don't drop buttons atop each other)
* Remove now-unnecessary hardcoded 30 px. space on the right side of the ExtensionInfoBar in favor of the new and more-accurate InfoBarView::EndX()
* Make ExtensionInfoBar menu animate down properly during infobar creation by calling OffsetY() instead of hardcoding a division by 2
* Remove erroneous -1s when setting ExtensionView bounds
* Fix calls to InfoBarAnimated() always getting |completed| reversed
BUG=27832, 39102
TEST=ConfirmInfoBars should put buttons on left by text and link on right by close button
Review URL: http://codereview.chromium.org/6596058
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76406 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/views')
18 files changed, 435 insertions, 302 deletions
diff --git a/chrome/browser/ui/views/infobars/after_translate_infobar.cc b/chrome/browser/ui/views/infobars/after_translate_infobar.cc index d9092ff..2a12950 100644 --- a/chrome/browser/ui/views/infobars/after_translate_infobar.cc +++ b/chrome/browser/ui/views/infobars/after_translate_infobar.cc @@ -15,41 +15,17 @@ AfterTranslateInfoBar::AfterTranslateInfoBar( TranslateInfoBarDelegate* delegate) : TranslateInfoBarBase(delegate), + label_1_(NULL), + label_2_(NULL), + label_3_(NULL), + original_language_menu_button_(NULL), + target_language_menu_button_(NULL), + revert_button_(NULL), + options_menu_button_(NULL), original_language_menu_model_(delegate, LanguagesMenuModel::ORIGINAL), target_language_menu_model_(delegate, LanguagesMenuModel::TARGET), options_menu_model_(delegate), swapped_language_buttons_(false) { - std::vector<string16> strings; - GetDelegate()->GetAfterTranslateStrings(&strings, &swapped_language_buttons_); - DCHECK_EQ(3U, strings.size()); - - label_1_ = CreateLabel(strings[0]); - AddChildView(label_1_); - - original_language_menu_button_ = CreateMenuButton(string16(), true, this); - target_language_menu_button_ = CreateMenuButton(string16(), true, this); - AddChildView(swapped_language_buttons_ ? - target_language_menu_button_ : original_language_menu_button_); - - label_2_ = CreateLabel(strings[1]); - AddChildView(label_2_); - - AddChildView(swapped_language_buttons_ ? - original_language_menu_button_ : target_language_menu_button_); - - label_3_ = CreateLabel(strings[2]); - AddChildView(label_3_); - - revert_button_ = CreateTextButton(this, - l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT), false); - AddChildView(revert_button_); - - options_menu_button_ = CreateMenuButton( - l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this); - AddChildView(options_menu_button_); - - OriginalLanguageChanged(); - TargetLanguageChanged(); } AfterTranslateInfoBar::~AfterTranslateInfoBar() { @@ -58,10 +34,11 @@ AfterTranslateInfoBar::~AfterTranslateInfoBar() { void AfterTranslateInfoBar::Layout() { TranslateInfoBarBase::Layout(); - int available_width = GetAvailableWidth(); + int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth()); gfx::Size label_1_size = label_1_->GetPreferredSize(); label_1_->SetBounds(StartX(), OffsetY(this, label_1_size), - label_1_size.width(), label_1_size.height()); + std::min(label_1_size.width(), available_width), label_1_size.height()); + available_width = std::max(0, available_width - label_1_size.width()); views::MenuButton* first_button = original_language_menu_button_; views::MenuButton* second_button = target_language_menu_button_; @@ -74,7 +51,9 @@ void AfterTranslateInfoBar::Layout() { gfx::Size label_2_size = label_2_->GetPreferredSize(); label_2_->SetBounds(first_button->bounds().right() + kButtonInLabelSpacing, - OffsetY(this, label_2_size), label_2_size.width(), label_2_size.height()); + OffsetY(this, label_2_size), + std::min(label_2_size.width(), available_width), label_2_size.height()); + available_width = std::max(0, available_width - label_2_size.width()); gfx::Size second_button_size = second_button->GetPreferredSize(); second_button->SetBounds(label_2_->bounds().right() + kButtonInLabelSpacing, @@ -83,7 +62,8 @@ void AfterTranslateInfoBar::Layout() { gfx::Size label_3_size = label_3_->GetPreferredSize(); label_3_->SetBounds(second_button->bounds().right() + kButtonInLabelSpacing, - OffsetY(this, label_3_size), label_3_size.width(), label_3_size.height()); + OffsetY(this, label_3_size), + std::min(label_3_size.width(), available_width), label_3_size.height()); gfx::Size revert_button_size = revert_button_->GetPreferredSize(); revert_button_->SetBounds(label_3_->bounds().right() + kButtonInLabelSpacing, @@ -91,10 +71,58 @@ void AfterTranslateInfoBar::Layout() { revert_button_size.width(), revert_button_size.height()); gfx::Size options_size = options_menu_button_->GetPreferredSize(); - options_menu_button_->SetBounds(available_width - options_size.width(), + options_menu_button_->SetBounds(EndX() - options_size.width(), OffsetY(this, options_size), options_size.width(), options_size.height()); } +void AfterTranslateInfoBar::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (!is_add || (child != this) || (label_1_ != NULL)) { + TranslateInfoBarBase::ViewHierarchyChanged(is_add, parent, child); + return; + } + + std::vector<string16> strings; + GetDelegate()->GetAfterTranslateStrings(&strings, &swapped_language_buttons_); + DCHECK_EQ(3U, strings.size()); + + label_1_ = CreateLabel(strings[0]); + AddChildView(label_1_); + + original_language_menu_button_ = CreateMenuButton(string16(), true, this); + target_language_menu_button_ = CreateMenuButton(string16(), true, this); + AddChildView(swapped_language_buttons_ ? + target_language_menu_button_ : original_language_menu_button_); + + label_2_ = CreateLabel(strings[1]); + AddChildView(label_2_); + + AddChildView(swapped_language_buttons_ ? + original_language_menu_button_ : target_language_menu_button_); + + label_3_ = CreateLabel(strings[2]); + AddChildView(label_3_); + + revert_button_ = CreateTextButton(this, + l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_REVERT), false); + AddChildView(revert_button_); + + options_menu_button_ = CreateMenuButton( + l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this); + AddChildView(options_menu_button_); + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + TranslateInfoBarBase::ViewHierarchyChanged(is_add, parent, child); + + // These must happen after adding all children because they trigger layout, + // which assumes that particular children (e.g. the close button) have already + // been added. + OriginalLanguageChanged(); + TargetLanguageChanged(); +} + void AfterTranslateInfoBar::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == revert_button_) @@ -103,6 +131,18 @@ void AfterTranslateInfoBar::ButtonPressed(views::Button* sender, TranslateInfoBarBase::ButtonPressed(sender, event); } +int AfterTranslateInfoBar::ContentMinimumWidth() const { + return + (kButtonInLabelSpacing + + original_language_menu_button_->GetPreferredSize().width() + + kButtonInLabelSpacing) + + (kButtonInLabelSpacing + + target_language_menu_button_->GetPreferredSize().width() + + kButtonInLabelSpacing) + + (kButtonInLabelSpacing + revert_button_->GetPreferredSize().width()) + + (kEndOfLabelSpacing + options_menu_button_->GetPreferredSize().width()); +} + void AfterTranslateInfoBar::OriginalLanguageChanged() { UpdateLanguageButtonText(original_language_menu_button_, LanguagesMenuModel::ORIGINAL); @@ -115,21 +155,11 @@ void AfterTranslateInfoBar::TargetLanguageChanged() { void AfterTranslateInfoBar::RunMenu(View* source, const gfx::Point& pt) { if (source == original_language_menu_button_) { - if (!original_language_menu_.get()) { - original_language_menu_.reset( - new views::Menu2(&original_language_menu_model_)); - } original_language_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); } else if (source == target_language_menu_button_) { - if (!target_language_menu_.get()) { - target_language_menu_.reset( - new views::Menu2(&target_language_menu_model_)); - } target_language_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); } else { DCHECK_EQ(options_menu_button_, source); - if (!options_menu_.get()) - options_menu_.reset(new views::Menu2(&options_menu_model_)); options_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); } } diff --git a/chrome/browser/ui/views/infobars/after_translate_infobar.h b/chrome/browser/ui/views/infobars/after_translate_infobar.h index 8dc53bf..c1cd254 100644 --- a/chrome/browser/ui/views/infobars/after_translate_infobar.h +++ b/chrome/browser/ui/views/infobars/after_translate_infobar.h @@ -27,7 +27,9 @@ class AfterTranslateInfoBar : public TranslateInfoBarBase, // TranslateInfoBarBase: virtual void Layout(); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); virtual void ButtonPressed(views::Button* sender, const views::Event& event); + virtual int ContentMinimumWidth() const; virtual void OriginalLanguageChanged(); virtual void TargetLanguageChanged(); @@ -47,14 +49,14 @@ class AfterTranslateInfoBar : public TranslateInfoBarBase, views::TextButton* revert_button_; views::MenuButton* options_menu_button_; - scoped_ptr<views::Menu2> original_language_menu_; LanguagesMenuModel original_language_menu_model_; + scoped_ptr<views::Menu2> original_language_menu_; - scoped_ptr<views::Menu2> target_language_menu_; LanguagesMenuModel target_language_menu_model_; + scoped_ptr<views::Menu2> target_language_menu_; - scoped_ptr<views::Menu2> options_menu_; OptionsMenuModel options_menu_model_; + scoped_ptr<views::Menu2> options_menu_; // True if the target language comes before the original one. bool swapped_language_buttons_; diff --git a/chrome/browser/ui/views/infobars/before_translate_infobar.cc b/chrome/browser/ui/views/infobars/before_translate_infobar.cc index b3b5f06..303b1fe 100644 --- a/chrome/browser/ui/views/infobars/before_translate_infobar.cc +++ b/chrome/browser/ui/views/infobars/before_translate_infobar.cc @@ -15,51 +15,18 @@ BeforeTranslateInfoBar::BeforeTranslateInfoBar( TranslateInfoBarDelegate* delegate) : TranslateInfoBarBase(delegate), + label_1_(NULL), + label_2_(NULL), + language_menu_button_(NULL), + accept_button_(NULL), + deny_button_(NULL), never_translate_button_(NULL), always_translate_button_(NULL), + options_menu_button_(NULL), languages_menu_model_(delegate, LanguagesMenuModel::ORIGINAL), - options_menu_model_(delegate) { - size_t offset = 0; - string16 text(l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE, - string16(), &offset)); - - label_1_ = CreateLabel(text.substr(0, offset)); - AddChildView(label_1_); - - language_menu_button_ = CreateMenuButton(string16(), true, this); - AddChildView(language_menu_button_); - - label_2_ = CreateLabel(text.substr(offset)); - AddChildView(label_2_); - - accept_button_ = CreateTextButton(this, - l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_ACCEPT), false); - AddChildView(accept_button_); - - deny_button_ = CreateTextButton(this, - l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_DENY), false); - AddChildView(deny_button_); - - const string16& language(delegate->GetLanguageDisplayableNameAt( - delegate->original_language_index())); - if (delegate->ShouldShowNeverTranslateButton()) { - DCHECK(!delegate->ShouldShowAlwaysTranslateButton()); - never_translate_button_ = CreateTextButton(this, - l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE, - language), false); - AddChildView(never_translate_button_); - } else if (delegate->ShouldShowAlwaysTranslateButton()) { - always_translate_button_ = CreateTextButton(this, - l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE, - language), false); - AddChildView(always_translate_button_); - } - - options_menu_button_ = CreateMenuButton( - l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this); - AddChildView(options_menu_button_); - - OriginalLanguageChanged(); + languages_menu_(new views::Menu2(&languages_menu_model_)), + options_menu_model_(delegate), + options_menu_(new views::Menu2(&options_menu_model_)) { } BeforeTranslateInfoBar::~BeforeTranslateInfoBar() { @@ -68,10 +35,11 @@ BeforeTranslateInfoBar::~BeforeTranslateInfoBar() { void BeforeTranslateInfoBar::Layout() { TranslateInfoBarBase::Layout(); - int available_width = GetAvailableWidth(); + int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth()); gfx::Size label_1_size = label_1_->GetPreferredSize(); label_1_->SetBounds(StartX(), OffsetY(this, label_1_size), - label_1_size.width(), label_1_size.height()); + std::min(label_1_size.width(), available_width), label_1_size.height()); + available_width = std::max(0, available_width - label_1_size.width()); gfx::Size language_button_size = language_menu_button_->GetPreferredSize(); language_menu_button_->SetBounds( @@ -82,7 +50,8 @@ void BeforeTranslateInfoBar::Layout() { gfx::Size label_2_size = label_2_->GetPreferredSize(); label_2_->SetBounds( language_menu_button_->bounds().right() + kButtonInLabelSpacing, - OffsetY(this, label_2_size), label_2_size.width(), label_2_size.height()); + OffsetY(this, label_2_size), + std::min(label_2_size.width(), available_width), label_2_size.height()); gfx::Size accept_button_size = accept_button_->GetPreferredSize(); accept_button_->SetBounds(label_2_->bounds().right() + kEndOfLabelSpacing, @@ -112,10 +81,85 @@ void BeforeTranslateInfoBar::Layout() { } gfx::Size options_size = options_menu_button_->GetPreferredSize(); - options_menu_button_->SetBounds(available_width - options_size.width(), + options_menu_button_->SetBounds(EndX() - options_size.width(), OffsetY(this, options_size), options_size.width(), options_size.height()); } +void BeforeTranslateInfoBar::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (!is_add || (child != this) || (label_1_ != NULL)) { + TranslateInfoBarBase::ViewHierarchyChanged(is_add, parent, child); + return; + } + + size_t offset = 0; + string16 text(l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_BEFORE_MESSAGE, + string16(), &offset)); + + label_1_ = CreateLabel(text.substr(0, offset)); + AddChildView(label_1_); + + language_menu_button_ = CreateMenuButton(string16(), true, this); + AddChildView(language_menu_button_); + + label_2_ = CreateLabel(text.substr(offset)); + AddChildView(label_2_); + + accept_button_ = CreateTextButton(this, + l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_ACCEPT), false); + AddChildView(accept_button_); + + deny_button_ = CreateTextButton(this, + l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_DENY), false); + AddChildView(deny_button_); + + TranslateInfoBarDelegate* delegate = GetDelegate(); + const string16& language(delegate->GetLanguageDisplayableNameAt( + delegate->original_language_index())); + if (delegate->ShouldShowNeverTranslateButton()) { + DCHECK(!delegate->ShouldShowAlwaysTranslateButton()); + never_translate_button_ = CreateTextButton(this, + l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_NEVER_TRANSLATE, + language), false); + AddChildView(never_translate_button_); + } else if (delegate->ShouldShowAlwaysTranslateButton()) { + always_translate_button_ = CreateTextButton(this, + l10n_util::GetStringFUTF16(IDS_TRANSLATE_INFOBAR_ALWAYS_TRANSLATE, + language), false); + AddChildView(always_translate_button_); + } + + options_menu_button_ = CreateMenuButton( + l10n_util::GetStringUTF16(IDS_TRANSLATE_INFOBAR_OPTIONS), false, this); + AddChildView(options_menu_button_); + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + TranslateInfoBarBase::ViewHierarchyChanged(is_add, parent, child); + + // This must happen after adding all children because it triggers layout, + // which assumes that particular children (e.g. the close button) have already + // been added. + OriginalLanguageChanged(); +} + +int BeforeTranslateInfoBar::ContentMinimumWidth() const { + return + (kButtonInLabelSpacing + + language_menu_button_->GetPreferredSize().width() + + kButtonInLabelSpacing) + + (kEndOfLabelSpacing + accept_button_->GetPreferredSize().width()) + + (kButtonButtonSpacing + deny_button_->GetPreferredSize().width()) + + ((never_translate_button_ == NULL) ? 0 : + (kButtonButtonSpacing + + never_translate_button_->GetPreferredSize().width())) + + ((always_translate_button_ == NULL) ? 0 : + (kButtonButtonSpacing + + always_translate_button_->GetPreferredSize().width())) + + (kEndOfLabelSpacing + options_menu_button_->GetPreferredSize().width()); +} + void BeforeTranslateInfoBar::ButtonPressed(views::Button* sender, const views::Event& event) { TranslateInfoBarDelegate* delegate = GetDelegate(); @@ -139,13 +183,9 @@ void BeforeTranslateInfoBar::OriginalLanguageChanged() { void BeforeTranslateInfoBar::RunMenu(View* source, const gfx::Point& pt) { if (source == language_menu_button_) { - if (!languages_menu_.get()) - languages_menu_.reset(new views::Menu2(&languages_menu_model_)); languages_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); } else { DCHECK_EQ(options_menu_button_, source); - if (!options_menu_.get()) - options_menu_.reset(new views::Menu2(&options_menu_model_)); options_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT); } } diff --git a/chrome/browser/ui/views/infobars/before_translate_infobar.h b/chrome/browser/ui/views/infobars/before_translate_infobar.h index efe8dc7..546b33f 100644 --- a/chrome/browser/ui/views/infobars/before_translate_infobar.h +++ b/chrome/browser/ui/views/infobars/before_translate_infobar.h @@ -28,6 +28,8 @@ class BeforeTranslateInfoBar : public TranslateInfoBarBase, // TranslateInfoBarBase: virtual void Layout(); virtual void ButtonPressed(views::Button* sender, const views::Event& event); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); + virtual int ContentMinimumWidth() const; virtual void OriginalLanguageChanged(); // views::ViewMenuDelegate: @@ -47,11 +49,11 @@ class BeforeTranslateInfoBar : public TranslateInfoBarBase, views::TextButton* always_translate_button_; views::MenuButton* options_menu_button_; - scoped_ptr<views::Menu2> languages_menu_; LanguagesMenuModel languages_menu_model_; + scoped_ptr<views::Menu2> languages_menu_; - scoped_ptr<views::Menu2> options_menu_; OptionsMenuModel options_menu_model_; + scoped_ptr<views::Menu2> options_menu_; DISALLOW_COPY_AND_ASSIGN(BeforeTranslateInfoBar); }; diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.cc b/chrome/browser/ui/views/infobars/confirm_infobar.cc index d4ae788..d190cfc 100644 --- a/chrome/browser/ui/views/infobars/confirm_infobar.cc +++ b/chrome/browser/ui/views/infobars/confirm_infobar.cc @@ -19,80 +19,73 @@ InfoBar* ConfirmInfoBarDelegate::CreateInfoBar() { ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate) : InfoBarView(delegate), - initialized_(false) { - label_ = CreateLabel(delegate->GetMessageText()); - - ok_button_ = CreateTextButton(this, - (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) ? - delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK) : - string16(), - delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK)); - cancel_button_ = CreateTextButton(this, - (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) ? - delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL) : - string16(), - delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_CANCEL)); - - link_ = CreateLink(delegate->GetLinkText(), this, background()->get_color()); + label_(NULL), + ok_button_(NULL), + cancel_button_(NULL), + link_(NULL) { } ConfirmInfoBar::~ConfirmInfoBar() { - if (!initialized_) { - delete label_; - delete ok_button_; - delete cancel_button_; - delete link_; - } } void ConfirmInfoBar::Layout() { InfoBarView::Layout(); - int available_width = InfoBarView::GetAvailableWidth(); - int ok_button_width = 0; - int cancel_button_width = 0; - gfx::Size ok_size = ok_button_->GetPreferredSize(); - gfx::Size cancel_size = cancel_button_->GetPreferredSize(); - - if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) { - ok_button_width = ok_size.width(); - } else { - ok_button_->SetVisible(false); - } - if (GetDelegate()->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) { - cancel_button_width = cancel_size.width(); - } else { - cancel_button_->SetVisible(false); - } - - cancel_button_->SetBounds(available_width - cancel_button_width, - OffsetY(this, cancel_size), cancel_size.width(), cancel_size.height()); - int spacing = cancel_button_width > 0 ? kButtonButtonSpacing : 0; - ok_button_->SetBounds(cancel_button_->x() - spacing - ok_button_width, - OffsetY(this, ok_size), ok_size.width(), ok_size.height()); - + int available_width = std::max(0, EndX() - StartX() - ContentMinimumWidth()); gfx::Size label_size = label_->GetPreferredSize(); label_->SetBounds(StartX(), OffsetY(this, label_size), std::min(label_size.width(), available_width), label_size.height()); + available_width = std::max(0, available_width - label_size.width()); + + int button_x = label_->bounds().right() + kEndOfLabelSpacing; + if (ok_button_ != NULL) { + gfx::Size ok_size = ok_button_->GetPreferredSize(); + ok_button_->SetBounds(button_x, OffsetY(this, ok_size), ok_size.width(), + ok_size.height()); + button_x += ok_size.width() + kButtonButtonSpacing; + } - // Now append the link to the label's right edge. - link_->SetVisible(!link_->GetText().empty()); - gfx::Size link_size = link_->GetPreferredSize(); - int link_x = label_->bounds().right() + kEndOfLabelSpacing; - int link_w = std::min(GetAvailableWidth() - link_x, link_size.width()); - link_->SetBounds(link_x, OffsetY(this, link_size), link_w, - link_size.height()); + if (cancel_button_ != NULL) { + gfx::Size cancel_size = cancel_button_->GetPreferredSize(); + cancel_button_->SetBounds(button_x, OffsetY(this, cancel_size), + cancel_size.width(), cancel_size.height()); + } + + if (link_ != NULL) { + gfx::Size link_size = link_->GetPreferredSize(); + int link_width = std::min(link_size.width(), available_width); + link_->SetBounds(EndX() - link_width, OffsetY(this, link_size), link_width, + link_size.height()); + } } void ConfirmInfoBar::ViewHierarchyChanged(bool is_add, View* parent, View* child) { - if (is_add && child == this && !initialized_) { + if (is_add && child == this && (label_ == NULL)) { + ConfirmInfoBarDelegate* delegate = GetDelegate(); + label_ = CreateLabel(delegate->GetMessageText()); AddChildView(label_); - AddChildView(ok_button_); - AddChildView(cancel_button_); - AddChildView(link_); - initialized_ = true; + + if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_OK) { + ok_button_ = CreateTextButton(this, + delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_OK), + delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_OK)); + AddChildView(ok_button_); + } + + if (delegate->GetButtons() & ConfirmInfoBarDelegate::BUTTON_CANCEL) { + cancel_button_ = CreateTextButton(this, + delegate->GetButtonLabel(ConfirmInfoBarDelegate::BUTTON_CANCEL), + delegate->NeedElevation(ConfirmInfoBarDelegate::BUTTON_CANCEL)); + AddChildView(cancel_button_); + } + + string16 link_text(delegate->GetLinkText()); + if (!link_text.empty()) { + link_ = CreateLink(link_text, this, background()->get_color()); + AddChildView(link_); + } } // This must happen after adding all other children so InfoBarView can ensure @@ -100,17 +93,13 @@ void ConfirmInfoBar::ViewHierarchyChanged(bool is_add, InfoBarView::ViewHierarchyChanged(is_add, parent, child); } -int ConfirmInfoBar::GetAvailableWidth() const { - return ok_button_->x() - kEndOfLabelSpacing; -} - void ConfirmInfoBar::ButtonPressed(views::Button* sender, const views::Event& event) { ConfirmInfoBarDelegate* delegate = GetDelegate(); - if (sender == ok_button_) { + if ((ok_button_ != NULL) && sender == ok_button_) { if (delegate->Accept()) RemoveInfoBar(); - } else if (sender == cancel_button_) { + } else if ((cancel_button_ != NULL) && (sender == cancel_button_)) { if (delegate->Cancel()) RemoveInfoBar(); } else { @@ -118,7 +107,19 @@ void ConfirmInfoBar::ButtonPressed(views::Button* sender, } } +int ConfirmInfoBar::ContentMinimumWidth() const { + int width = (link_ == NULL) ? 0 : kEndOfLabelSpacing; // Space before link + int before_cancel_spacing = kEndOfLabelSpacing; + if (ok_button_ != NULL) { + width += kEndOfLabelSpacing + ok_button_->GetPreferredSize().width(); + before_cancel_spacing = kButtonButtonSpacing; + } + return width + ((cancel_button_ == NULL) ? 0 : + (before_cancel_spacing + cancel_button_->GetPreferredSize().width())); +} + void ConfirmInfoBar::LinkActivated(views::Link* source, int event_flags) { + DCHECK(link_ != NULL); DCHECK_EQ(link_, source); if (GetDelegate()->LinkClicked( event_utils::DispositionFromEventFlags(event_flags))) diff --git a/chrome/browser/ui/views/infobars/confirm_infobar.h b/chrome/browser/ui/views/infobars/confirm_infobar.h index be99c68..9ba0055 100644 --- a/chrome/browser/ui/views/infobars/confirm_infobar.h +++ b/chrome/browser/ui/views/infobars/confirm_infobar.h @@ -18,8 +18,6 @@ class TextButton; // An infobar that shows a message, up to two optional buttons, and an optional, // right-aligned link. This is commonly used to do things like: // "Would you like to do X? [Yes] [No] _Learn More_ [x]" -// TODO(pkasting): The above layout is the desired, but not current, layout; fix -// coming in a future patch. class ConfirmInfoBar : public InfoBarView, public views::LinkController { public: @@ -31,8 +29,8 @@ class ConfirmInfoBar : public InfoBarView, // InfoBarView: virtual void Layout(); virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); - virtual int GetAvailableWidth() const; virtual void ButtonPressed(views::Button* sender, const views::Event& event); + virtual int ContentMinimumWidth() const; // views::LinkController: virtual void LinkActivated(views::Link* source, int event_flags); @@ -44,8 +42,6 @@ class ConfirmInfoBar : public InfoBarView, views::TextButton* cancel_button_; views::Link* link_; - bool initialized_; - DISALLOW_COPY_AND_ASSIGN(ConfirmInfoBar); }; diff --git a/chrome/browser/ui/views/infobars/extension_infobar.cc b/chrome/browser/ui/views/infobars/extension_infobar.cc index 7d5a404..0d26942 100644 --- a/chrome/browser/ui/views/infobars/extension_infobar.cc +++ b/chrome/browser/ui/views/infobars/extension_infobar.cc @@ -32,15 +32,12 @@ InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() { namespace { // The horizontal margin between the menu and the Extension (HTML) view. static const int kMenuHorizontalMargin = 1; - -// The amount of space to the right of the Extension (HTML) view (to avoid -// overlapping the close button for the InfoBar). -static const int kFarRightMargin = 30; }; ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate) : InfoBarView(delegate), delegate_(delegate), + menu_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { delegate->set_observer(this); @@ -49,15 +46,8 @@ ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate) set_target_height((height > 0) ? (height + InfoBarBackground::kSeparatorLineHeight) : height); - // Setup the extension icon and its associated drop down menu. - SetupIconAndMenu(); - // Get notified of resize events for the ExtensionView. extension_view->SetContainer(this); - // We show the ExtensionView, but we don't want it deleted when we get - // destroyed, which happens on tab switching (for example). - extension_view->set_parent_owned(false); - AddChildView(extension_view); } ExtensionInfoBar::~ExtensionInfoBar() { @@ -71,12 +61,54 @@ void ExtensionInfoBar::Layout() { InfoBarView::Layout(); gfx::Size menu_size = menu_->GetPreferredSize(); - menu_->SetBounds(0, (height() - menu_size.height()) / 2, menu_size.width(), + menu_->SetBounds(StartX(), OffsetY(this, menu_size), menu_size.width(), menu_size.height()); - int x = menu_->bounds().right() + kMenuHorizontalMargin; - GetDelegate()->extension_host()->view()->SetBounds(x, 0, - width() - x - kFarRightMargin - 1, height() - 1); + GetDelegate()->extension_host()->view()->SetBounds( + menu_->bounds().right() + kMenuHorizontalMargin, 0, + std::max(0, EndX() - StartX() - ContentMinimumWidth()), height()); +} + +void ExtensionInfoBar::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (!is_add || (child != this) || (menu_ != NULL)) { + InfoBarView::ViewHierarchyChanged(is_add, parent, child); + return; + } + + menu_ = new views::MenuButton(NULL, std::wstring(), this, false); + menu_->SetVisible(false); + AddChildView(menu_); + + ExtensionHost* extension_host = GetDelegate()->extension_host(); + ExtensionView* extension_view = extension_host->view(); + // We show the ExtensionView, but we don't want it deleted when we get + // destroyed, which happens on tab switching (for example). + extension_view->set_parent_owned(false); + AddChildView(extension_view); + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + InfoBarView::ViewHierarchyChanged(is_add, parent, child); + + // This must happen after adding all children because it can trigger layout, + // which assumes that particular children (e.g. the close button) have already + // been added. + const Extension* extension = extension_host->extension(); + int image_size = Extension::EXTENSION_ICON_BITTY; + ExtensionResource icon_resource = extension->GetIconResource( + image_size, ExtensionIconSet::MATCH_EXACTLY); + if (!icon_resource.relative_path().empty()) { + tracker_.LoadImage(extension, icon_resource, + gfx::Size(image_size, image_size), ImageLoadingTracker::DONT_CACHE); + } else { + OnImageLoaded(NULL, icon_resource, 0); + } +} + +int ExtensionInfoBar::ContentMinimumWidth() const { + return menu_->GetPreferredSize().width() + kMenuHorizontalMargin; } void ExtensionInfoBar::OnExtensionMouseMove(ExtensionView* view) { @@ -160,23 +192,6 @@ void ExtensionInfoBar::RunMenu(View* source, const gfx::Point& pt) { options_menu_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPLEFT); } -void ExtensionInfoBar::SetupIconAndMenu() { - menu_ = new views::MenuButton(NULL, std::wstring(), this, false); - menu_->SetVisible(false); - AddChildView(menu_); - - const Extension* extension = GetDelegate()->extension_host()->extension(); - int image_size = Extension::EXTENSION_ICON_BITTY; - ExtensionResource icon_resource = extension->GetIconResource( - image_size, ExtensionIconSet::MATCH_EXACTLY); - if (!icon_resource.relative_path().empty()) { - tracker_.LoadImage(extension, icon_resource, - gfx::Size(image_size, image_size), ImageLoadingTracker::DONT_CACHE); - } else { - OnImageLoaded(NULL, icon_resource, 0); - } -} - ExtensionInfoBarDelegate* ExtensionInfoBar::GetDelegate() { return delegate_ ? delegate_->AsExtensionInfoBarDelegate() : NULL; } diff --git a/chrome/browser/ui/views/infobars/extension_infobar.h b/chrome/browser/ui/views/infobars/extension_infobar.h index 9a7068a..fe87fe3 100644 --- a/chrome/browser/ui/views/infobars/extension_infobar.h +++ b/chrome/browser/ui/views/infobars/extension_infobar.h @@ -32,6 +32,8 @@ class ExtensionInfoBar : public InfoBarView, // InfoBarView: virtual void Layout(); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); + virtual int ContentMinimumWidth() const; // ExtensionView::Container: virtual void OnExtensionMouseMove(ExtensionView* view); @@ -49,10 +51,6 @@ class ExtensionInfoBar : public InfoBarView, // views::ViewMenuDelegate: virtual void RunMenu(View* source, const gfx::Point& pt); - // Setup the menu button showing the small extension icon and its dropdown - // menu. - void SetupIconAndMenu(); - ExtensionInfoBarDelegate* GetDelegate(); NotificationRegistrar notification_registrar_; diff --git a/chrome/browser/ui/views/infobars/infobar_container.cc b/chrome/browser/ui/views/infobars/infobar_container.cc index f7148f1..a5c489b 100644 --- a/chrome/browser/ui/views/infobars/infobar_container.cc +++ b/chrome/browser/ui/views/infobars/infobar_container.cc @@ -90,18 +90,6 @@ AccessibilityTypes::Role InfoBarContainer::GetAccessibleRole() { return AccessibilityTypes::ROLE_GROUPING; } -void InfoBarContainer::ViewHierarchyChanged(bool is_add, - View* parent, - View* child) { - if (parent == this && child->parent() == this) { - if (delegate_) { - // An InfoBar child was added or removed. Tell the delegate it needs to - // re-layout since our preferred size will have changed. - delegate_->InfoBarContainerSizeChanged(false); - } - } -} - void InfoBarContainer::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/browser/ui/views/infobars/infobar_container.h b/chrome/browser/ui/views/infobars/infobar_container.h index 9d03acb..9210c1b9 100644 --- a/chrome/browser/ui/views/infobars/infobar_container.h +++ b/chrome/browser/ui/views/infobars/infobar_container.h @@ -56,7 +56,6 @@ class InfoBarContainer : public AccessiblePaneView, virtual gfx::Size GetPreferredSize(); virtual void Layout(); virtual AccessibilityTypes::Role GetAccessibleRole(); - virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); // NotificationObserver: virtual void Observe(NotificationType type, diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc index 09b5c8d..e125800 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.cc +++ b/chrome/browser/ui/views/infobars/infobar_view.cc @@ -6,10 +6,10 @@ #include "base/message_loop.h" #include "base/utf_string_conversions.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/ui/views/infobars/infobar_background.h" #include "chrome/browser/ui/views/infobars/infobar_button_border.h" #include "chrome/browser/ui/views/infobars/infobar_container.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -45,8 +45,7 @@ InfoBarView::InfoBarView(InfoBarDelegate* delegate) : InfoBar(delegate), delegate_(delegate), icon_(NULL), - ALLOW_THIS_IN_INITIALIZER_LIST( - close_button_(new views::ImageButton(this))), + close_button_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)), target_height_(kDefaultTargetHeight) { set_parent_owned(false); // InfoBar deletes itself at the appropriate time. @@ -57,25 +56,6 @@ InfoBarView::InfoBarView(InfoBarDelegate* delegate) (infobar_type == InfoBarDelegate::WARNING_TYPE) ? IDS_ACCNAME_INFOBAR_WARNING : IDS_ACCNAME_INFOBAR_PAGE_ACTION)); - SkBitmap* image = delegate->GetIcon(); - if (image) { - icon_ = new views::ImageView; - icon_->SetImage(image); - AddChildView(icon_); - } - - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - close_button_->SetImage(views::CustomButton::BS_NORMAL, - rb.GetBitmapNamed(IDR_CLOSE_BAR)); - close_button_->SetImage(views::CustomButton::BS_HOT, - rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); - close_button_->SetImage(views::CustomButton::BS_PUSHED, - rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); - close_button_->SetAccessibleName( - l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); - close_button_->SetFocusable(true); - AddChildView(close_button_); - animation_.reset(new ui::SlideAnimation(this)); animation_->SetTweenType(ui::Tween::LINEAR); } @@ -89,7 +69,7 @@ void InfoBarView::Open() { // size. animation_->Reset(1.0); if (container_) - container_->InfoBarAnimated(false); + container_->InfoBarAnimated(true); } void InfoBarView::AnimateClose() { @@ -107,6 +87,8 @@ void InfoBarView::AnimateClose() { void InfoBarView::Close() { parent()->RemoveChildView(this); + if (container_) + container_->InfoBarAnimated(true); // Note that we only tell the delegate we're closed here, and not when we're // simply destroyed (by virtue of a tab switch or being moved from window to // window), since this action can cause the delegate to destroy itself. @@ -261,12 +243,13 @@ void InfoBarView::Layout() { gfx::Size icon_size = icon_->GetPreferredSize(); icon_->SetBounds(start_x, OffsetY(this, icon_size), icon_size.width(), icon_size.height()); + start_x += icon_->bounds().right(); } gfx::Size button_size = close_button_->GetPreferredSize(); - close_button_->SetBounds(width() - kHorizontalPadding - button_size.width(), - OffsetY(this, button_size), button_size.width(), - button_size.height()); + close_button_->SetBounds(std::max(start_x + ContentMinimumWidth(), + width() - kHorizontalPadding - button_size.width()), + OffsetY(this, button_size), button_size.width(), button_size.height()); } void InfoBarView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { @@ -289,6 +272,28 @@ void InfoBarView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { if (GetFocusManager()) GetFocusManager()->AddFocusChangeListener(this); NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT); + + if (close_button_ == NULL) { + SkBitmap* image = delegate_->GetIcon(); + if (image) { + icon_ = new views::ImageView; + icon_->SetImage(image); + AddChildView(icon_); + } + + close_button_ = new views::ImageButton(this); + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + close_button_->SetImage(views::CustomButton::BS_NORMAL, + rb.GetBitmapNamed(IDR_CLOSE_BAR)); + close_button_->SetImage(views::CustomButton::BS_HOT, + rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); + close_button_->SetImage(views::CustomButton::BS_PUSHED, + rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); + close_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); + close_button_->SetFocusable(true); + AddChildView(close_button_); + } } else { DestroyFocusTracker(false); // NULL our container_ pointer so that if Animation::Stop results in @@ -305,7 +310,7 @@ void InfoBarView::ViewHierarchyChanged(bool is_add, View* parent, View* child) { } // For accessibility, ensure the close button is the last child view. - if ((parent == this) && (child != close_button_) && + if ((close_button_ != NULL) && (parent == this) && (child != close_button_) && (close_button_->parent() == this) && (GetChildViewAt(child_count() - 1) != close_button_)) { RemoveChildView(close_button_); @@ -324,12 +329,11 @@ void InfoBarView::ButtonPressed(views::Button* sender, void InfoBarView::AnimationProgressed(const ui::Animation* animation) { if (container_) - container_->InfoBarAnimated(true); + container_->InfoBarAnimated(false); } -int InfoBarView::GetAvailableWidth() const { - const int kCloseButtonSpacing = 12; - return close_button_->x() - kCloseButtonSpacing - StartX(); +int InfoBarView::ContentMinimumWidth() const { + return 0; } void InfoBarView::RemoveInfoBar() const { @@ -338,7 +342,16 @@ void InfoBarView::RemoveInfoBar() const { } int InfoBarView::StartX() const { - return ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding; + // Ensure we don't return a value greater than EndX(), so children can safely + // set something's width to "EndX() - StartX()" without risking that being + // negative. + return std::min(EndX(), + ((icon_ != NULL) ? icon_->bounds().right() : 0) + kHorizontalPadding); +} + +int InfoBarView::EndX() const { + const int kCloseButtonSpacing = 12; + return close_button_->x() - kCloseButtonSpacing; } int InfoBarView::CenterY(const gfx::Size prefsize) const { @@ -367,12 +380,8 @@ void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) { } void InfoBarView::AnimationEnded(const ui::Animation* animation) { - if (container_) { - container_->InfoBarAnimated(false); - - if (!animation_->IsShowing()) - Close(); - } + if (container_ && !animation_->IsShowing()) + Close(); } void InfoBarView::DestroyFocusTracker(bool restore_focus) { diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h index bca50ac..31d3dee 100644 --- a/chrome/browser/ui/views/infobars/infobar_view.h +++ b/chrome/browser/ui/views/infobars/infobar_view.h @@ -116,9 +116,10 @@ class InfoBarView : public InfoBar, // ui::AnimationDelegate: virtual void AnimationProgressed(const ui::Animation* animation); - // Returns the available width of the View for use by child view layout, - // excluding the close button. - virtual int GetAvailableWidth() const; + // Returns the minimum width the content (that is, everything between the icon + // and the close button) can be shrunk to. This is used to prevent the close + // button from overlapping views that cannot be shrunk any further. + virtual int ContentMinimumWidth() const; // Removes our associated InfoBarDelegate from the associated TabContents. // (Will lead to this InfoBar being closed). @@ -128,9 +129,10 @@ class InfoBarView : public InfoBar, ui::SlideAnimation* animation() { return animation_.get(); } - // Returns the initial x coordinate of the usable area for subclasses to lay + // These return x coordinates delimiting the usable area for subclasses to lay // out their controls. int StartX() const; + int EndX() const; // Returns a centered y-position of a control of height specified in // |prefsize| within the standard InfoBar height. Stable during an animation. diff --git a/chrome/browser/ui/views/infobars/link_infobar.cc b/chrome/browser/ui/views/infobars/link_infobar.cc index 73a227b..9548b58 100644 --- a/chrome/browser/ui/views/infobars/link_infobar.cc +++ b/chrome/browser/ui/views/infobars/link_infobar.cc @@ -16,19 +16,10 @@ InfoBar* LinkInfoBarDelegate::CreateInfoBar() { // LinkInfoBar ---------------------------------------------------------------- LinkInfoBar::LinkInfoBar(LinkInfoBarDelegate* delegate) - : InfoBarView(delegate) { - size_t offset; - string16 message_text = delegate->GetMessageTextWithOffset(&offset); - DCHECK_NE(string16::npos, offset); - label_1_ = CreateLabel(message_text.substr(0, offset)); - AddChildView(label_1_); - - link_ = CreateLink(delegate->GetLinkText(), this, - background()->get_color()); - AddChildView(link_); - - label_2_ = CreateLabel(message_text.substr(offset)); - AddChildView(label_2_); + : InfoBarView(delegate), + label_1_(NULL), + link_(NULL), + label_2_(NULL) { } LinkInfoBar::~LinkInfoBar() { @@ -37,20 +28,48 @@ LinkInfoBar::~LinkInfoBar() { void LinkInfoBar::Layout() { InfoBarView::Layout(); + // TODO(pkasting): This isn't perfect; there are points when we should elide a + // view because its subsequent view will be too small to show an ellipsis. gfx::Size label_1_size = label_1_->GetPreferredSize(); + int available_width = EndX() - StartX(); label_1_->SetBounds(StartX(), OffsetY(this, label_1_size), - label_1_size.width(), label_1_size.height()); + std::min(label_1_size.width(), available_width), label_1_size.height()); + available_width = std::max(0, available_width - label_1_size.width()); gfx::Size link_size = link_->GetPreferredSize(); link_->SetBounds(label_1_->bounds().right(), OffsetY(this, link_size), - link_size.width(), link_size.height()); + std::min(link_size.width(), available_width), link_size.height()); + available_width = std::max(0, available_width - link_size.width()); gfx::Size label_2_size = label_2_->GetPreferredSize(); label_2_->SetBounds(link_->bounds().right(), OffsetY(this, label_2_size), - label_2_size.width(), label_2_size.height()); + std::min(label_2_size.width(), available_width), label_2_size.height()); +} + +void LinkInfoBar::ViewHierarchyChanged(bool is_add, View* parent, View* child) { + if (is_add && (child == this) && (label_1_ == NULL)) { + LinkInfoBarDelegate* delegate = GetDelegate(); + size_t offset; + string16 message_text = delegate->GetMessageTextWithOffset(&offset); + DCHECK_NE(string16::npos, offset); + label_1_ = CreateLabel(message_text.substr(0, offset)); + AddChildView(label_1_); + + link_ = CreateLink(delegate->GetLinkText(), this, + background()->get_color()); + AddChildView(link_); + + label_2_ = CreateLabel(message_text.substr(offset)); + AddChildView(label_2_); + } + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + InfoBarView::ViewHierarchyChanged(is_add, parent, child); } void LinkInfoBar::LinkActivated(views::Link* source, int event_flags) { + DCHECK(link_ != NULL); DCHECK_EQ(link_, source); if (GetDelegate()->LinkClicked( event_utils::DispositionFromEventFlags(event_flags))) diff --git a/chrome/browser/ui/views/infobars/link_infobar.h b/chrome/browser/ui/views/infobars/link_infobar.h index cb8380b..26ab7e4 100644 --- a/chrome/browser/ui/views/infobars/link_infobar.h +++ b/chrome/browser/ui/views/infobars/link_infobar.h @@ -25,6 +25,7 @@ class LinkInfoBar : public InfoBarView, // views::LinkController: virtual void LinkActivated(views::Link* source, int event_flags); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); LinkInfoBarDelegate* GetDelegate(); diff --git a/chrome/browser/ui/views/infobars/translate_infobar_base.cc b/chrome/browser/ui/views/infobars/translate_infobar_base.cc index 5b944f1..7337098 100644 --- a/chrome/browser/ui/views/infobars/translate_infobar_base.cc +++ b/chrome/browser/ui/views/infobars/translate_infobar_base.cc @@ -48,23 +48,34 @@ TranslateInfoBarBase::TranslateInfoBarBase(TranslateInfoBarDelegate* delegate) : InfoBarView(delegate), normal_background_(InfoBarDelegate::PAGE_ACTION_TYPE), error_background_(InfoBarDelegate::WARNING_TYPE) { - background_color_animation_.reset(new ui::SlideAnimation(this)); - background_color_animation_->SetTweenType(ui::Tween::LINEAR); - background_color_animation_->SetSlideDuration(500); - TranslateInfoBarDelegate::BackgroundAnimationType animation = - GetDelegate()->background_animation_type(); - if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) { - background_color_animation_->Show(); - } else if (animation == TranslateInfoBarDelegate::ERROR_TO_NORMAL) { - // Hide() runs the animation in reverse. - background_color_animation_->Reset(1.0); - background_color_animation_->Hide(); - } } TranslateInfoBarBase::~TranslateInfoBarBase() { } +void TranslateInfoBarBase::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (is_add && (child == this) && (background_color_animation_ == NULL)) { + background_color_animation_.reset(new ui::SlideAnimation(this)); + background_color_animation_->SetTweenType(ui::Tween::LINEAR); + background_color_animation_->SetSlideDuration(500); + TranslateInfoBarDelegate::BackgroundAnimationType animation = + GetDelegate()->background_animation_type(); + if (animation == TranslateInfoBarDelegate::NORMAL_TO_ERROR) { + background_color_animation_->Show(); + } else if (animation == TranslateInfoBarDelegate::ERROR_TO_NORMAL) { + // Hide() runs the animation in reverse. + background_color_animation_->Reset(1.0); + background_color_animation_->Hide(); + } + } + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + InfoBarView::ViewHierarchyChanged(is_add, parent, child); +} + void TranslateInfoBarBase::UpdateLanguageButtonText( views::MenuButton* button, LanguagesMenuModel::LanguageType language_type) { diff --git a/chrome/browser/ui/views/infobars/translate_infobar_base.h b/chrome/browser/ui/views/infobars/translate_infobar_base.h index 145279f..11df83e 100644 --- a/chrome/browser/ui/views/infobars/translate_infobar_base.h +++ b/chrome/browser/ui/views/infobars/translate_infobar_base.h @@ -28,6 +28,9 @@ class TranslateInfoBarBase : public TranslateInfoBarView, protected: static const int kButtonInLabelSpacing; + // InfoBarView: + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); + // Sets the text of the provided language menu button to reflect the current // value from the delegate. void UpdateLanguageButtonText(views::MenuButton* button, diff --git a/chrome/browser/ui/views/infobars/translate_message_infobar.cc b/chrome/browser/ui/views/infobars/translate_message_infobar.cc index 1ccbefc..0fddf35 100644 --- a/chrome/browser/ui/views/infobars/translate_message_infobar.cc +++ b/chrome/browser/ui/views/infobars/translate_message_infobar.cc @@ -11,15 +11,8 @@ TranslateMessageInfoBar::TranslateMessageInfoBar( TranslateInfoBarDelegate* delegate) : TranslateInfoBarBase(delegate), + label_(NULL), button_(NULL) { - label_ = CreateLabel(delegate->GetMessageInfoBarText()); - AddChildView(label_); - - string16 button_text = delegate->GetMessageInfoBarButtonText(); - if (!button_text.empty()) { - button_ = CreateTextButton(this, button_text, false); - AddChildView(button_); - } } TranslateMessageInfoBar::~TranslateMessageInfoBar() { @@ -29,21 +22,38 @@ void TranslateMessageInfoBar::Layout() { TranslateInfoBarBase::Layout(); gfx::Size label_size = label_->GetPreferredSize(); - int available_width = GetAvailableWidth() - StartX(); - gfx::Size button_size; - if (button_) { - button_size = button_->GetPreferredSize(); - available_width -= (button_size.width() + kButtonInLabelSpacing); - } label_->SetBounds(StartX(), OffsetY(this, label_size), - std::min(label_size.width(), available_width), label_size.height()); + std::min(label_size.width(), + std::max(0, EndX() - StartX() - ContentMinimumWidth())), + label_size.height()); if (button_) { + gfx::Size button_size = button_->GetPreferredSize(); button_->SetBounds(label_->bounds().right() + kButtonInLabelSpacing, OffsetY(this, button_size), button_size.width(), button_size.height()); } } +void TranslateMessageInfoBar::ViewHierarchyChanged(bool is_add, + View* parent, + View* child) { + if (is_add && (child == this) && (label_ == NULL)) { + TranslateInfoBarDelegate* delegate = GetDelegate(); + label_ = CreateLabel(delegate->GetMessageInfoBarText()); + AddChildView(label_); + + string16 button_text = delegate->GetMessageInfoBarButtonText(); + if (!button_text.empty()) { + button_ = CreateTextButton(this, button_text, false); + AddChildView(button_); + } + } + + // This must happen after adding all other children so InfoBarView can ensure + // the close button is the last child. + TranslateInfoBarBase::ViewHierarchyChanged(is_add, parent, child); +} + void TranslateMessageInfoBar::ButtonPressed(views::Button* sender, const views::Event& event) { if (sender == button_) @@ -51,3 +61,8 @@ void TranslateMessageInfoBar::ButtonPressed(views::Button* sender, else TranslateInfoBarBase::ButtonPressed(sender, event); } + +int TranslateMessageInfoBar::ContentMinimumWidth() const { + return (button_ != NULL) ? + (button_->GetPreferredSize().width() + kButtonInLabelSpacing) : 0; +} diff --git a/chrome/browser/ui/views/infobars/translate_message_infobar.h b/chrome/browser/ui/views/infobars/translate_message_infobar.h index a503df5..c6a27fe 100644 --- a/chrome/browser/ui/views/infobars/translate_message_infobar.h +++ b/chrome/browser/ui/views/infobars/translate_message_infobar.h @@ -17,7 +17,9 @@ class TranslateMessageInfoBar : public TranslateInfoBarBase { // TranslateInfoBarBase: virtual void Layout(); + virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child); virtual void ButtonPressed(views::Button* sender, const views::Event& event); + virtual int ContentMinimumWidth() const; views::Label* label_; views::TextButton* button_; |