Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: views/controls/textfield/textfield_view_model.cc

Issue 5857002: no native implementation of Textfield. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: " Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 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 "views/controls/textfield/textfield_view_model.h"
6
7 #include <algorithm>
8
9 #include "base/i18n/word_iterator.h"
10 #include "base/logging.h"
11 #include "base/utf_string_conversions.h"
12 #include "gfx/font.h"
13
14 namespace views {
15
16 TextfieldViewModel::TextfieldViewModel()
17 : cursor_pos_(0),
18 begin_(0),
19 end_(0),
20 is_password_(false) {
21 }
22
23 TextfieldViewModel::~TextfieldViewModel() {
24 }
25
26 void TextfieldViewModel::PopulateFragments(TextFragments* fragments) const {
27 DCHECK(fragments);
28 fragments->clear();
29 if (HasSelection()) {
30 int begin = std::min(begin_, end_);
31 int end = std::max(begin_, end_);
32 if (begin != 0) {
33 fragments->push_back(TextFragment(0, begin, false));
34 }
35 fragments->push_back(TextFragment(begin, end, true));
36 int len = text_.length();
37 if (end != len) {
38 fragments->push_back(TextFragment(end, len, false));
39 }
40 } else {
41 fragments->push_back(TextFragment(0, text_.length(), false));
42 }
43 }
44
45 bool TextfieldViewModel::SetText(const string16& text) {
46 bool changed = text_ != text;
47 if (changed) {
48 text_ = text;
49 if (cursor_pos_ > text.length()) {
50 cursor_pos_ = text.length();
51 }
52 }
53 ClearSelection();
54 return changed;
55 }
56
57 void TextfieldViewModel::Insert(char16 c) {
58 if (HasSelection())
59 DeleteSelection();
60 text_.insert(cursor_pos_, 1, c);
sky 2010/12/15 20:31:27 Meta question. Isn't it possible for a visual char
oshima 2010/12/16 01:15:19 Yes, you're correct. This only works in UTF16/UCS-
61 cursor_pos_++;
62 }
63
64 void TextfieldViewModel::Replace(char16 c) {
65 if (!HasSelection())
66 Delete();
67 Insert(c);
68 }
69
70 void TextfieldViewModel::Append(const string16& text) {
71 text_ += text;
72 }
73
74 bool TextfieldViewModel::Delete() {
75 if (HasSelection()) {
76 DeleteSelection();
77 return true;
78 } else if (text_.length() > cursor_pos_) {
79 text_.erase(cursor_pos_, 1);
80 return true;
81 }
82 return false;
83 }
84
85 bool TextfieldViewModel::Backspace() {
86 if (HasSelection()) {
87 DeleteSelection();
88 return true;
89 } else if(cursor_pos_ > 0) {
90 cursor_pos_--;
91 text_.erase(cursor_pos_, 1);
92 return true;
93 }
94 return false;
95 }
96
97 void TextfieldViewModel::MoveCursorLeft(bool select) {
98 // support bidi
99 int old = cursor_pos_;
100 if (cursor_pos_ > 0)
101 cursor_pos_--;
102 if (select)
103 Select(old, cursor_pos_);
104 else
105 ClearSelection();
106 }
107
108 void TextfieldViewModel::MoveCursorRight(bool select) {
109 int old = cursor_pos_;
110 // support bidi
111 cursor_pos_ = std::min(text_.length(), cursor_pos_ + 1);
112 if (select)
113 Select(old, cursor_pos_);
114 else
115 ClearSelection();
116 }
117
118 void TextfieldViewModel::MoveCursorToPreviousWord(bool select) {
119 // Notes: We always iterate words from the begining.
120 // This is probably fast enough for our usage, but we may
121 // want to modify WordIterator so that it can start from the
122 // middle of string and adnvace backwards.
sky 2010/12/15 20:31:27 adnvace -> advance
oshima 2010/12/16 01:15:19 Done.
123 WordIterator iter(&text_, WordIterator::BREAK_WORD);
124 bool success = iter.Init();
125 DCHECK(success);
126 if (!success)
127 return;
128 int prev = 0;
129 while (iter.Advance()) {
130 if (iter.IsWord()) {
131 int old = cursor_pos_;
132 size_t begin = iter.pos() - iter.GetWord().length();
133 if (begin == cursor_pos_) {
134 // The cursor is at the beginning of a word.
135 // Move to previous word.
136 cursor_pos_ = prev;
137 } else if(iter.pos() >= cursor_pos_) {
138 // The cursor is in the middle or at the end of a word.
139 // Move to the top of current word.
140 cursor_pos_ = begin;
141 } else {
142 prev = iter.pos() - iter.GetWord().length();
143 continue;
144 }
145 if (select)
146 Select(old, cursor_pos_);
147 else
148 ClearSelection();
149 break;
150 }
151 }
152 }
153
154 void TextfieldViewModel::MoveCursorToNextWord(bool select) {
155 WordIterator iter(&text_, WordIterator::BREAK_WORD);
156 bool success = iter.Init();
157 DCHECK(success);
158 if (!success)
159 return;
160 while (iter.Advance()) {
161 if (iter.IsWord() && iter.pos() > cursor_pos_) {
162 int old = cursor_pos_;
163 cursor_pos_ = iter.pos();
164 if (select)
165 Select(old, cursor_pos_);
166 else
167 ClearSelection();
168 break;
169 }
170 }
171 }
172
173 void TextfieldViewModel::MoveCursorToStart(bool select) {
174 int old = cursor_pos_;
175 cursor_pos_ = 0;
176 if (select)
177 Select(old, cursor_pos_);
178 else
179 ClearSelection();
180 }
181
182 void TextfieldViewModel::MoveCursorToEnd(bool select) {
183 int old = cursor_pos_;
184 cursor_pos_ = text_.length();
185 if (select)
186 Select(old, cursor_pos_);
187 else
188 ClearSelection();
189 }
190
191 bool TextfieldViewModel::MoveCursorTo(size_t pos, bool select) {
192 if (cursor_pos_ != pos) {
193 if (select)
194 Select(cursor_pos_, pos);
195 else
196 ClearSelection();
197 cursor_pos_ = pos;
198 return true;
199 }
200 return false;
201 }
202
203 gfx::Rect TextfieldViewModel::GetCursorBounds(const gfx::Font& font) const {
204 string16 text = GetVisibleText();
205 int x = font.GetStringWidth(UTF16ToWide(text.substr(0U, cursor_pos_)));
206 int h = font.GetHeight();
207 DCHECK(x >= 0);
208 if (text.length() == cursor_pos_) {
209 return gfx::Rect(x, 0, 0, h);
210 } else {
211 int x_end =
212 font.GetStringWidth(UTF16ToWide(text.substr(0U, cursor_pos_ + 1U)));
213 return gfx::Rect(x, 0, x_end - x, h);
214 }
215 }
216
217 string16 TextfieldViewModel::GetSelectedText() const {
218 return text_.substr(std::min(begin_, end_),
219 std::abs(static_cast<long>(end_ - begin_)));
sky 2010/12/15 20:31:27 static_cast<size_t>
oshima 2010/12/16 01:15:19 size_t is unsigned. using long to make it signed f
220 }
221
222 void TextfieldViewModel::SelectAll() {
223 begin_ = 0;
224 end_ = text_.length();
sky 2010/12/15 20:31:27 Select(0, text_.length())
oshima 2010/12/16 01:15:19 Done.
225 }
226
227 void TextfieldViewModel::ClearSelection() {
228 begin_ = end_ = cursor_pos_;
229 }
230
231 void TextfieldViewModel::Select(size_t old, size_t end) {
232 if (old == end) return; // no action
233
234 DCHECK(0 <= old && old <= text_.length());
235 DCHECK(0 <= end && old <= text_.length());
236 if (!HasSelection()) {
237 // first time
238 begin_ = old;
239 end_ = end;
240 } else {
241 end_ = end;
242 }
243 }
244
245 bool TextfieldViewModel::HasSelection() const {
246 return begin_ != end_;
247 }
248
249 void TextfieldViewModel::DeleteSelection() {
250 DCHECK(HasSelection());
251 size_t n = std::abs(static_cast<long>(end_ - begin_));
sky 2010/12/15 20:31:27 static_cast<size_t>
oshima 2010/12/16 01:15:19 same here.
252 size_t begin = std::min(begin_, end_);
253 text_.erase(begin, n);
254 cursor_pos_ = begin;
255 ClearSelection();
256 }
257
258 string16 TextfieldViewModel::GetVisibleText(size_t begin, size_t end) const {
259 DCHECK(end >= begin);
260 if (is_password_) {
261 return string16(end - begin, '*');
262 }
263 return text_.substr(begin, end - begin);
264 }
265
266 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698