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
= base::SplitString(
54 text
, base::string16(1, '\n'),
55 base::KEEP_WHITESPACE
, base::SPLIT_WANT_ALL
);
58 for (std::list
<DecoratedTextfield
*>::iterator iter
= textfields_
.begin();
59 iter
!= textfields_
.end(); ++iter
) {
60 (*iter
)->SetText(i
< strings
.size() ? strings
[i
++] : base::string16());
63 for (; i
< strings
.size(); ++i
) {
64 textfields_
.push_back(new DecoratedTextfield(
66 textfields_
.front()->GetPlaceholderText(),
68 AddChildView(textfields_
.back());
69 PreferredSizeChanged();
73 base::string16
ExpandingTextfield::GetText() {
74 base::string16 text
= textfields_
.front()->text();
75 std::list
<DecoratedTextfield
*>::const_iterator iter
= ++textfields_
.begin();
76 while (iter
!= textfields_
.end()) {
77 text
+= base::ASCIIToUTF16("\n") + (*iter
++)->text();
79 base::TrimWhitespace(text
, base::TRIM_ALL
, &text
);
83 void ExpandingTextfield::SetInvalid(bool invalid
) {
84 textfields_
.front()->SetInvalid(invalid
);
87 void ExpandingTextfield::SetDefaultWidthInCharacters(int chars
) {
88 ForEachTextfield(&DecoratedTextfield::set_default_width_in_chars
, chars
);
91 void ExpandingTextfield::SetPlaceholderText(const base::string16
& placeholder
) {
92 ForEachTextfield
<views::Textfield
, const base::string16
&>(
93 &DecoratedTextfield::set_placeholder_text
, placeholder
);
96 void ExpandingTextfield::SetIcon(const gfx::Image
& icon
) {
97 textfields_
.front()->SetIcon(icon
);
100 void ExpandingTextfield::SetTooltipIcon(const base::string16
& text
) {
101 textfields_
.front()->SetTooltipIcon(text
);
104 void ExpandingTextfield::SetEditable(bool editable
) {
105 ForEachTextfield(&DecoratedTextfield::SetEditable
, editable
);
108 const char* ExpandingTextfield::GetClassName() const {
109 return kViewClassName
;
112 void ExpandingTextfield::ContentsChanged(views::Textfield
* sender
,
113 const base::string16
& new_contents
) {
114 if (textfields_
.size() > 1 && sender
== textfields_
.back() &&
115 !new_contents
.empty()) {
116 textfields_
.push_back(
117 new DecoratedTextfield(base::string16(),
118 sender
->GetPlaceholderText(),
120 AddChildView(textfields_
.back());
121 PreferredSizeChanged();
124 controller_
->ContentsChanged(sender
, new_contents
);
127 bool ExpandingTextfield::HandleKeyEvent(views::Textfield
* sender
,
128 const ui::KeyEvent
& key_event
) {
129 return controller_
->HandleKeyEvent(sender
, key_event
);
132 bool ExpandingTextfield::HandleMouseEvent(views::Textfield
* sender
,
133 const ui::MouseEvent
& mouse_event
) {
134 return controller_
->HandleMouseEvent(sender
, mouse_event
);
137 template <typename BaseType
, typename Param
>
138 void ExpandingTextfield::ForEachTextfield(
139 void (BaseType::* f
)(Param
), Param p
) const {
140 for (std::list
<DecoratedTextfield
*>::const_iterator iter
=
142 iter
!= textfields_
.end(); ++iter
) {
143 base::Bind(f
, base::Unretained(*iter
), p
).Run();
147 } // namespace autofill