| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #include "chrome/browser/ui/views/autofill/expanding_textfield.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/strings/string_split.h" | |
| 11 #include "base/strings/string_util.h" | |
| 12 #include "base/strings/utf_string_conversions.h" | |
| 13 #include "chrome/browser/ui/views/autofill/decorated_textfield.h" | |
| 14 #include "ui/views/layout/box_layout.h" | |
| 15 | |
| 16 namespace autofill { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // The vertical padding between textfields. | |
| 21 const int kManualInputRowPadding = 10; | |
| 22 | |
| 23 } // namespace | |
| 24 | |
| 25 // static | |
| 26 const char ExpandingTextfield::kViewClassName[] = "autofill/ExpandingTextfield"; | |
| 27 | |
| 28 ExpandingTextfield::ExpandingTextfield( | |
| 29 const base::string16& default_value, | |
| 30 const base::string16& placeholder, | |
| 31 bool multiline, | |
| 32 views::TextfieldController* controller) | |
| 33 : controller_(controller) { | |
| 34 textfields_.push_back( | |
| 35 new DecoratedTextfield(base::string16(), placeholder, this)); | |
| 36 if (multiline) { | |
| 37 textfields_.push_back( | |
| 38 new DecoratedTextfield(base::string16(), placeholder, this)); | |
| 39 } | |
| 40 SetText(default_value); | |
| 41 | |
| 42 for (std::list<DecoratedTextfield*>::iterator iter = textfields_.begin(); | |
| 43 iter != textfields_.end(); ++iter) { | |
| 44 AddChildView(*iter); | |
| 45 } | |
| 46 | |
| 47 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, | |
| 48 kManualInputRowPadding)); | |
| 49 } | |
| 50 | |
| 51 ExpandingTextfield::~ExpandingTextfield() {} | |
| 52 | |
| 53 void ExpandingTextfield::SetText(const base::string16& text) { | |
| 54 textfields_.front()->SetText(text); | |
| 55 std::vector<base::string16> strings = base::SplitString( | |
| 56 text, base::string16(1, '\n'), | |
| 57 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 58 | |
| 59 size_t i = 0; | |
| 60 for (std::list<DecoratedTextfield*>::iterator iter = textfields_.begin(); | |
| 61 iter != textfields_.end(); ++iter) { | |
| 62 (*iter)->SetText(i < strings.size() ? strings[i++] : base::string16()); | |
| 63 } | |
| 64 | |
| 65 for (; i < strings.size(); ++i) { | |
| 66 textfields_.push_back(new DecoratedTextfield( | |
| 67 strings[i], | |
| 68 textfields_.front()->GetPlaceholderText(), | |
| 69 this)); | |
| 70 AddChildView(textfields_.back()); | |
| 71 PreferredSizeChanged(); | |
| 72 } | |
| 73 } | |
| 74 | |
| 75 base::string16 ExpandingTextfield::GetText() { | |
| 76 base::string16 text = textfields_.front()->text(); | |
| 77 std::list<DecoratedTextfield*>::const_iterator iter = ++textfields_.begin(); | |
| 78 while (iter != textfields_.end()) { | |
| 79 text += base::ASCIIToUTF16("\n") + (*iter++)->text(); | |
| 80 } | |
| 81 base::TrimWhitespace(text, base::TRIM_ALL, &text); | |
| 82 return text; | |
| 83 } | |
| 84 | |
| 85 void ExpandingTextfield::SetInvalid(bool invalid) { | |
| 86 textfields_.front()->SetInvalid(invalid); | |
| 87 } | |
| 88 | |
| 89 void ExpandingTextfield::SetDefaultWidthInCharacters(int chars) { | |
| 90 ForEachTextfield(&DecoratedTextfield::set_default_width_in_chars, chars); | |
| 91 } | |
| 92 | |
| 93 void ExpandingTextfield::SetPlaceholderText(const base::string16& placeholder) { | |
| 94 ForEachTextfield<views::Textfield, const base::string16&>( | |
| 95 &DecoratedTextfield::set_placeholder_text, placeholder); | |
| 96 } | |
| 97 | |
| 98 void ExpandingTextfield::SetIcon(const gfx::Image& icon) { | |
| 99 textfields_.front()->SetIcon(icon); | |
| 100 } | |
| 101 | |
| 102 void ExpandingTextfield::SetTooltipIcon(const base::string16& text) { | |
| 103 textfields_.front()->SetTooltipIcon(text); | |
| 104 } | |
| 105 | |
| 106 void ExpandingTextfield::SetEditable(bool editable) { | |
| 107 ForEachTextfield(&DecoratedTextfield::SetEditable, editable); | |
| 108 } | |
| 109 | |
| 110 const char* ExpandingTextfield::GetClassName() const { | |
| 111 return kViewClassName; | |
| 112 } | |
| 113 | |
| 114 void ExpandingTextfield::ContentsChanged(views::Textfield* sender, | |
| 115 const base::string16& new_contents) { | |
| 116 if (textfields_.size() > 1 && sender == textfields_.back() && | |
| 117 !new_contents.empty()) { | |
| 118 textfields_.push_back( | |
| 119 new DecoratedTextfield(base::string16(), | |
| 120 sender->GetPlaceholderText(), | |
| 121 this)); | |
| 122 AddChildView(textfields_.back()); | |
| 123 PreferredSizeChanged(); | |
| 124 } | |
| 125 | |
| 126 controller_->ContentsChanged(sender, new_contents); | |
| 127 } | |
| 128 | |
| 129 bool ExpandingTextfield::HandleKeyEvent(views::Textfield* sender, | |
| 130 const ui::KeyEvent& key_event) { | |
| 131 return controller_->HandleKeyEvent(sender, key_event); | |
| 132 } | |
| 133 | |
| 134 bool ExpandingTextfield::HandleMouseEvent(views::Textfield* sender, | |
| 135 const ui::MouseEvent& mouse_event) { | |
| 136 return controller_->HandleMouseEvent(sender, mouse_event); | |
| 137 } | |
| 138 | |
| 139 template <typename BaseType, typename Param> | |
| 140 void ExpandingTextfield::ForEachTextfield( | |
| 141 void (BaseType::* f)(Param), Param p) const { | |
| 142 for (std::list<DecoratedTextfield*>::const_iterator iter = | |
| 143 textfields_.begin(); | |
| 144 iter != textfields_.end(); ++iter) { | |
| 145 base::Bind(f, base::Unretained(*iter), p).Run(); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 } // namespace autofill | |
| OLD | NEW |