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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/infobars/alternate_nav_infobar_view.h" 6 7 #include "base/logging.h" 8 #include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h" 9 #include "ui/base/window_open_disposition.h" 10 #include "ui/gfx/text_elider.h" 11 #include "ui/views/controls/label.h" 12 #include "ui/views/controls/link.h" 13 14 15 // AlternateNavInfoBarDelegate ------------------------------------------------- 16 17 // static 18 scoped_ptr<infobars::InfoBar> AlternateNavInfoBarDelegate::CreateInfoBar( 19 scoped_ptr<AlternateNavInfoBarDelegate> delegate) { 20 return scoped_ptr<infobars::InfoBar>( 21 new AlternateNavInfoBarView(delegate.Pass())); 22 } 23 24 25 // AlternateNavInfoBarView ----------------------------------------------------- 26 27 AlternateNavInfoBarView::AlternateNavInfoBarView( 28 scoped_ptr<AlternateNavInfoBarDelegate> delegate) 29 : InfoBarView(delegate.PassAs<infobars::InfoBarDelegate>()), 30 label_1_(NULL), 31 link_(NULL), 32 label_2_(NULL) {} 33 34 AlternateNavInfoBarView::~AlternateNavInfoBarView() { 35 } 36 37 // static 38 void AlternateNavInfoBarView::ElideLabels(Labels* labels, int available_width) { 39 views::Label* last_label = labels->back(); 40 labels->pop_back(); 41 int used_width = 0; 42 for (Labels::iterator i(labels->begin()); i != labels->end(); ++i) 43 used_width += (*i)->GetPreferredSize().width(); 44 int last_label_width = std::min(last_label->GetPreferredSize().width(), 45 available_width - used_width); 46 if (last_label_width < last_label->GetMinimumSize().width()) { 47 last_label_width = 0; 48 if (!labels->empty()) 49 labels->back()->SetText(labels->back()->text() + gfx::kEllipsisUTF16); 50 } 51 last_label->SetSize(gfx::Size(last_label_width, last_label->height())); 52 if (!labels->empty()) 53 ElideLabels(labels, available_width - last_label_width); 54 } 55 56 void AlternateNavInfoBarView::Layout() { 57 InfoBarView::Layout(); 58 59 label_1_->SetText(label_1_text_); 60 link_->SetText(link_text_); 61 label_2_->SetText(label_2_text_); 62 Labels labels; 63 labels.push_back(label_1_); 64 labels.push_back(link_); 65 labels.push_back(label_2_); 66 ElideLabels(&labels, EndX() - StartX()); 67 68 label_1_->SetPosition(gfx::Point(StartX(), OffsetY(label_1_))); 69 link_->SetPosition(gfx::Point(label_1_->bounds().right(), OffsetY(link_))); 70 label_2_->SetPosition(gfx::Point(link_->bounds().right(), OffsetY(label_2_))); 71 } 72 73 void AlternateNavInfoBarView::ViewHierarchyChanged( 74 const ViewHierarchyChangedDetails& details) { 75 if (details.is_add && (details.child == this) && (label_1_ == NULL)) { 76 AlternateNavInfoBarDelegate* delegate = GetDelegate(); 77 size_t offset; 78 base::string16 message_text = delegate->GetMessageTextWithOffset(&offset); 79 DCHECK_NE(base::string16::npos, offset); 80 label_1_text_ = message_text.substr(0, offset); 81 label_1_ = CreateLabel(label_1_text_); 82 AddChildView(label_1_); 83 84 link_text_ = delegate->GetLinkText(); 85 link_ = CreateLink(link_text_, this); 86 AddChildView(link_); 87 88 label_2_text_ = message_text.substr(offset); 89 label_2_ = CreateLabel(label_2_text_); 90 AddChildView(label_2_); 91 } 92 93 // This must happen after adding all other children so InfoBarView can ensure 94 // the close button is the last child. 95 InfoBarView::ViewHierarchyChanged(details); 96 } 97 98 int AlternateNavInfoBarView::ContentMinimumWidth() const { 99 int label_1_width = label_1_->GetMinimumSize().width(); 100 return label_1_width ? label_1_width : link_->GetMinimumSize().width(); 101 } 102 103 void AlternateNavInfoBarView::LinkClicked(views::Link* source, 104 int event_flags) { 105 if (!owner()) 106 return; // We're closing; don't call anything, it might access the owner. 107 DCHECK(link_ != NULL); 108 DCHECK_EQ(link_, source); 109 if (GetDelegate()->LinkClicked(ui::DispositionFromEventFlags(event_flags))) 110 RemoveSelf(); 111 } 112 113 AlternateNavInfoBarDelegate* AlternateNavInfoBarView::GetDelegate() { 114 return static_cast<AlternateNavInfoBarDelegate*>(delegate()); 115 } 116