1 // Copyright 2014 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.
5 #include "chrome/browser/ui/views/autofill/expanding_textfield.h"
8 #include "base/strings/string_split.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/ui/views/autofill/decorated_textfield.h"
12 #include "ui/views/layout/box_layout.h"
18 // The vertical padding between textfields.
19 const int kManualInputRowPadding
= 10;
24 const char ExpandingTextfield::kViewClassName
[] = "autofill/ExpandingTextfield";
26 ExpandingTextfield::ExpandingTextfield(
27 const base::string16
& default_value
,
28 const base::string16
& placeholder
,
30 views::TextfieldController
* controller
)
31 : controller_(controller
) {
32 textfields_
.push_back(
33 new DecoratedTextfield(base::string16(), placeholder
, this));
35 textfields_
.push_back(
36 new DecoratedTextfield(base::string16(), placeholder
, this));
38 SetText(default_value
);
40 for (std::list
<DecoratedTextfield
*>::iterator iter
= textfields_
.begin();
41 iter
!= textfields_
.end(); ++iter
) {
45 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical
, 0, 0,
46 kManualInputRowPadding
));
49 ExpandingTextfield::~ExpandingTextfield() {}
51 void ExpandingTextfield::SetText(const base::string16
& text
) {
52 textfields_
.front()->SetText(text
);
53 std::vector
<base::string16
> strings
;
54 base::SplitStringDontTrim(text
, '\n', &strings
);
57 for (std::list
<DecoratedTextfield
*>::iterator iter
= textfields_
.begin();
58 iter
!= textfields_
.end(); ++iter
) {
59 (*iter
)->SetText(i
< strings
.size() ? strings
[i
++] : base::string16());
62 for (; i
< strings
.size(); ++i
) {
63 textfields_
.push_back(new DecoratedTextfield(
65 textfields_
.front()->GetPlaceholderText(),
67 AddChildView(textfields_
.back());
68 PreferredSizeChanged();
72 base::string16
ExpandingTextfield::GetText() {
73 base::string16 text
= textfields_
.front()->text();
74 std::list
<DecoratedTextfield
*>::const_iterator iter
= ++textfields_
.begin();
75 while (iter
!= textfields_
.end()) {
76 text
+= base::ASCIIToUTF16("\n") + (*iter
++)->text();
78 base::TrimWhitespace(text
, base::TRIM_ALL
, &text
);
82 void ExpandingTextfield::SetInvalid(bool invalid
) {
83 textfields_
.front()->SetInvalid(invalid
);
86 void ExpandingTextfield::SetDefaultWidthInCharacters(int chars
) {
87 ForEachTextfield(&DecoratedTextfield::set_default_width_in_chars
, chars
);
90 void ExpandingTextfield::SetPlaceholderText(const base::string16
& placeholder
) {
91 ForEachTextfield
<views::Textfield
, const base::string16
&>(
92 &DecoratedTextfield::set_placeholder_text
, placeholder
);
95 void ExpandingTextfield::SetIcon(const gfx::Image
& icon
) {
96 textfields_
.front()->SetIcon(icon
);
99 void ExpandingTextfield::SetTooltipIcon(const base::string16
& text
) {
100 textfields_
.front()->SetTooltipIcon(text
);
103 void ExpandingTextfield::SetEditable(bool editable
) {
104 ForEachTextfield(&DecoratedTextfield::SetEditable
, editable
);
107 const char* ExpandingTextfield::GetClassName() const {
108 return kViewClassName
;
111 void ExpandingTextfield::ContentsChanged(views::Textfield
* sender
,
112 const base::string16
& new_contents
) {
113 if (textfields_
.size() > 1 && sender
== textfields_
.back() &&
114 !new_contents
.empty()) {
115 textfields_
.push_back(
116 new DecoratedTextfield(base::string16(),
117 sender
->GetPlaceholderText(),
119 AddChildView(textfields_
.back());
120 PreferredSizeChanged();
123 controller_
->ContentsChanged(sender
, new_contents
);
126 bool ExpandingTextfield::HandleKeyEvent(views::Textfield
* sender
,
127 const ui::KeyEvent
& key_event
) {
128 return controller_
->HandleKeyEvent(sender
, key_event
);
131 bool ExpandingTextfield::HandleMouseEvent(views::Textfield
* sender
,
132 const ui::MouseEvent
& mouse_event
) {
133 return controller_
->HandleMouseEvent(sender
, mouse_event
);
136 template <typename BaseType
, typename Param
>
137 void ExpandingTextfield::ForEachTextfield(
138 void (BaseType::* f
)(Param
), Param p
) const {
139 for (std::list
<DecoratedTextfield
*>::const_iterator iter
=
141 iter
!= textfields_
.end(); ++iter
) {
142 base::Bind(f
, base::Unretained(*iter
), p
).Run();
146 } // namespace autofill