alternate_nav_infobar_view.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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
18scoped_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
27AlternateNavInfoBarView::AlternateNavInfoBarView(
28    scoped_ptr<AlternateNavInfoBarDelegate> delegate)
29    : InfoBarView(delegate.PassAs<infobars::InfoBarDelegate>()),
30      label_1_(NULL),
31      link_(NULL),
32      label_2_(NULL) {}
33
34AlternateNavInfoBarView::~AlternateNavInfoBarView() {
35}
36
37// static
38void 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
56void 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
73void 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
98int AlternateNavInfoBarView::ContentMinimumWidth() {
99  int label_1_width = label_1_->GetMinimumSize().width();
100  return label_1_width ? label_1_width : link_->GetMinimumSize().width();
101}
102
103void 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
113AlternateNavInfoBarDelegate* AlternateNavInfoBarView::GetDelegate() {
114  return static_cast<AlternateNavInfoBarDelegate*>(delegate());
115}
116