Home | History | Annotate | Download | only in infobars
      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