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

Unified Diff: views/controls/textfield/textfield_views_model.cc

Issue 7265011: RenderText API Outline. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add TODO comments, revise cursor movement API, etc. Created 9 years, 5 months 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 side-by-side diff with in-line comments
Download patch
Index: views/controls/textfield/textfield_views_model.cc
diff --git a/views/controls/textfield/textfield_views_model.cc b/views/controls/textfield/textfield_views_model.cc
index 1605546307bf7ef519883e9f5765c571f779d9e3..15aa039b3a1acc5883176d00533df6a1324c59cc 100644
--- a/views/controls/textfield/textfield_views_model.cc
+++ b/views/controls/textfield/textfield_views_model.cc
@@ -13,8 +13,9 @@
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/range/range.h"
+#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
-#include "views/controls/textfield/text_style.h"
+#include "ui/gfx/render_text.h"
#include "views/controls/textfield/textfield.h"
#include "views/views_delegate.h"
@@ -256,116 +257,8 @@ class DeleteEdit : public Edit {
}
};
-struct TextStyleRange {
- TextStyleRange(const TextStyle* s, size_t start, size_t end)
- : style(s),
- range(start, end) {
- }
- TextStyleRange(const TextStyle* s, const ui::Range& r)
- : style(s),
- range(r) {
- }
- const TextStyle *style;
- ui::Range range;
-};
-
} // namespace internal
-namespace {
-
-using views::internal::TextStyleRange;
-
-static bool TextStyleRangeComparator(const TextStyleRange* i,
- const TextStyleRange* j) {
- return i->range.start() < j->range.start();
-}
-
-#ifndef NDEBUG
-// A test function to check TextStyleRanges' invariant condition:
-// "no overlapping range".
-bool CheckInvariant(const TextStyleRanges* style_ranges) {
- TextStyleRanges copy = *style_ranges;
- std::sort(copy.begin(), copy.end(), TextStyleRangeComparator);
-
- for (TextStyleRanges::size_type i = 0; i < copy.size() - 1; i++) {
- ui::Range& former = copy[i]->range;
- ui::Range& latter = copy[i + 1]->range;
- if (former.is_empty()) {
- LOG(WARNING) << "Empty range at " << i << " :" << former;
- return false;
- }
- if (!former.IsValid()) {
- LOG(WARNING) << "Invalid range at " << i << " :" << former;
- return false;
- }
- if (former.GetMax() > latter.GetMin()) {
- LOG(WARNING) <<
- "Sorting error. former:" << former << " latter:" << latter;
- return false;
- }
- if (former.Intersects(latter)) {
- LOG(ERROR) << "overlapping style range found: former=" << former
- << ", latter=" << latter;
- return false;
- }
- }
- if ((*copy.rbegin())->range.is_empty()) {
- LOG(WARNING) << "Empty range at end";
- return false;
- }
- if (!(*copy.rbegin())->range.IsValid()) {
- LOG(WARNING) << "Invalid range at end";
- return false;
- }
- return true;
-}
-#endif
-
-void InsertStyle(TextStyleRanges* style_ranges,
- TextStyleRange* text_style_range) {
- const ui::Range& range = text_style_range->range;
- if (range.is_empty() || !range.IsValid()) {
- delete text_style_range;
- return;
- }
- CHECK(!range.is_reversed());
-
- // Invariant condition: all items in the range has no overlaps.
- TextStyleRanges::size_type index = 0;
- while (index < style_ranges->size()) {
- TextStyleRange* current = (*style_ranges)[index];
- if (range.Contains(current->range)) {
- style_ranges->erase(style_ranges->begin() + index);
- delete current;
- continue;
- } else if (current->range.Contains(range) &&
- range.start() != current->range.start() &&
- range.end() != current->range.end()) {
- // Split current style into two styles.
- style_ranges->push_back(
- new TextStyleRange(current->style,
- range.GetMax(), current->range.GetMax()));
- current->range.set_end(range.GetMin());
- } else if (range.Intersects(current->range)) {
- if (current->range.GetMax() <= range.GetMax()) {
- current->range.set_end(range.GetMin());
- } else {
- current->range.set_start(range.GetMax());
- }
- } else {
- // No change needed. Pass it through.
- }
- index ++;
- }
- // Add the new range at the end.
- style_ranges->push_back(text_style_range);
-#ifndef NDEBUG
- DCHECK(CheckInvariant(style_ranges));
-#endif
-}
-
-} // namespace
-
using internal::Edit;
using internal::DeleteEdit;
using internal::InsertEdit;
@@ -383,70 +276,19 @@ TextfieldViewsModel::Delegate::~Delegate() {
TextfieldViewsModel::TextfieldViewsModel(Delegate* delegate)
: delegate_(delegate),
- cursor_pos_(0),
- selection_start_(0),
- composition_start_(0),
- composition_end_(0),
+ render_text_(gfx::RenderText::CreateRenderText()),
is_password_(false),
- current_edit_(edit_history_.end()),
- sort_style_ranges_(false) {
+ current_edit_(edit_history_.end()) {
}
TextfieldViewsModel::~TextfieldViewsModel() {
ClearEditHistory();
ClearComposition();
- ClearAllTextStyles();
- TextStyles::iterator begin = text_styles_.begin();
- TextStyles::iterator end = text_styles_.end();
- while (begin != end) {
- TextStyles::iterator temp = begin;
- ++begin;
- delete *temp;
- }
+ delete render_text_;
oshima 2011/07/23 09:51:12 why not scoped_ptr?
msw 2011/07/25 05:09:54 Done.
}
-void TextfieldViewsModel::GetFragments(TextFragments* fragments) {
- static const TextStyle* kNormalStyle = new TextStyle();
-
- if (sort_style_ranges_) {
- sort_style_ranges_ = false;
- std::sort(style_ranges_.begin(), style_ranges_.end(),
- TextStyleRangeComparator);
- }
-
- // If a user is compositing text, use composition's style.
- // TODO(oshima): ask suzhe for expected behavior.
- const TextStyleRanges& ranges = composition_style_ranges_.size() > 0 ?
- composition_style_ranges_ : style_ranges_;
- TextStyleRanges::const_iterator next_ = ranges.begin();
-
- DCHECK(fragments);
- fragments->clear();
- size_t current = 0;
- size_t end = text_.length();
- while(next_ != ranges.end()) {
- const TextStyleRange* text_style_range = *next_++;
- const ui::Range& range = text_style_range->range;
- const TextStyle* style = text_style_range->style;
-
- DCHECK(!range.is_empty());
- DCHECK(range.IsValid());
- if (range.is_empty() || !range.IsValid())
- continue;
-
- size_t start = std::min(range.start(), end);
-
- if (start == end) // Exit loop if it reached the end.
- break;
- else if (current < start) // Fill the gap to next style with normal text.
- fragments->push_back(TextFragment(current, start, kNormalStyle));
-
- current = std::min(range.end(), end);
- fragments->push_back(TextFragment(start, current, style));
- }
- // If there is any text left add it as normal text.
- if (current != end)
- fragments->push_back(TextFragment(current, end, kNormalStyle));
+const string16& TextfieldViewsModel::GetText() const {
+ return render_text_->text();
}
bool TextfieldViewsModel::SetText(const string16& text) {
@@ -455,10 +297,10 @@ bool TextfieldViewsModel::SetText(const string16& text) {
ConfirmCompositionText();
changed = true;
}
- if (text_ != text) {
+ if (GetText() != text) {
if (changed) // No need to remember composition.
Undo();
- size_t old_cursor = cursor_pos_;
+ size_t old_cursor = render_text_->GetCursor();
size_t new_cursor = old_cursor > text.length() ? text.length() : old_cursor;
SelectAll();
// If there is a composition text, don't merge with previous edit.
@@ -469,7 +311,7 @@ bool TextfieldViewsModel::SetText(const string16& text) {
new_cursor,
text,
0U);
- cursor_pos_ = new_cursor;
+ render_text_->SetCursor(new_cursor);
}
ClearSelection();
return changed;
@@ -478,10 +320,10 @@ bool TextfieldViewsModel::SetText(const string16& text) {
void TextfieldViewsModel::Append(const string16& text) {
if (HasCompositionText())
ConfirmCompositionText();
- size_t save = cursor_pos_;
- MoveCursorToEnd(false);
+ size_t save = render_text_->GetCursor();
+ MoveCursorRight(gfx::LINE_BREAK, false);
InsertText(text);
- cursor_pos_ = save;
+ render_text_->SetCursor(save);
ClearSelection();
}
@@ -495,8 +337,9 @@ bool TextfieldViewsModel::Delete() {
DeleteSelection();
return true;
}
- if (text_.length() > cursor_pos_) {
- ExecuteAndRecordDelete(cursor_pos_, cursor_pos_ + 1, true);
+ if (GetText().length() > render_text_->GetCursor()) {
+ size_t cursor_position = render_text_->GetCursor();
+ ExecuteAndRecordDelete(cursor_position, cursor_position + 1, true);
return true;
}
return false;
@@ -512,194 +355,79 @@ bool TextfieldViewsModel::Backspace() {
DeleteSelection();
return true;
}
- if (cursor_pos_ > 0) {
- ExecuteAndRecordDelete(cursor_pos_, cursor_pos_ - 1, true);
+ if (render_text_->GetCursor() > 0) {
+ size_t cursor_position = render_text_->GetCursor();
+ ExecuteAndRecordDelete(cursor_position, cursor_position - 1, true);
return true;
}
return false;
}
-void TextfieldViewsModel::MoveCursorLeft(bool select) {
- if (HasCompositionText())
- ConfirmCompositionText();
- // TODO(oshima): support BIDI
- if (select) {
- if (cursor_pos_ > 0)
- cursor_pos_--;
- } else {
- if (HasSelection())
- cursor_pos_ = std::min(cursor_pos_, selection_start_);
- else if (cursor_pos_ > 0)
- cursor_pos_--;
- ClearSelection();
- }
+size_t TextfieldViewsModel::GetCursorPosition() const {
+ return render_text_->GetCursor();
}
-void TextfieldViewsModel::MoveCursorRight(bool select) {
+void TextfieldViewsModel::MoveCursorLeft(gfx::BreakType break_type,
+ bool select) {
if (HasCompositionText())
ConfirmCompositionText();
- // TODO(oshima): support BIDI
- if (select) {
- cursor_pos_ = std::min(text_.length(), cursor_pos_ + 1);
- } else {
- if (HasSelection())
- cursor_pos_ = std::max(cursor_pos_, selection_start_);
- else
- cursor_pos_ = std::min(text_.length(), cursor_pos_ + 1);
- ClearSelection();
- }
+ render_text_->MoveCursorLeft(break_type, select);
}
-void TextfieldViewsModel::MoveCursorToPreviousWord(bool select) {
+void TextfieldViewsModel::MoveCursorRight(gfx::BreakType break_type,
+ bool select) {
if (HasCompositionText())
ConfirmCompositionText();
- // Notes: We always iterate words from the begining.
- // This is probably fast enough for our usage, but we may
- // want to modify WordIterator so that it can start from the
- // middle of string and advance backwards.
- base::i18n::BreakIterator iter(text_, base::i18n::BreakIterator::BREAK_WORD);
- bool success = iter.Init();
- DCHECK(success);
- if (!success)
- return;
- int last = 0;
- while (iter.Advance()) {
- if (iter.IsWord()) {
- size_t begin = iter.pos() - iter.GetString().length();
- if (begin == cursor_pos_) {
- // The cursor is at the beginning of a word.
- // Move to previous word.
- break;
- } else if(iter.pos() >= cursor_pos_) {
- // The cursor is in the middle or at the end of a word.
- // Move to the top of current word.
- last = begin;
- break;
- } else {
- last = iter.pos() - iter.GetString().length();
- }
- }
- }
-
- cursor_pos_ = last;
- if (!select)
- ClearSelection();
+ render_text_->MoveCursorRight(break_type, select);
}
-void TextfieldViewsModel::MoveCursorToNextWord(bool select) {
+bool TextfieldViewsModel::MoveCursorTo(size_t pos, bool select) {
if (HasCompositionText())
ConfirmCompositionText();
- base::i18n::BreakIterator iter(text_, base::i18n::BreakIterator::BREAK_WORD);
- bool success = iter.Init();
- DCHECK(success);
- if (!success)
- return;
- size_t pos = 0;
- while (iter.Advance()) {
- pos = iter.pos();
- if (iter.IsWord() && pos > cursor_pos_) {
- break;
- }
- }
- cursor_pos_ = pos;
- if (!select)
- ClearSelection();
+ return render_text_->MoveCursorTo(pos, select);
}
-void TextfieldViewsModel::MoveCursorToHome(bool select) {
- MoveCursorTo(0, select);
-}
-
-void TextfieldViewsModel::MoveCursorToEnd(bool select) {
- MoveCursorTo(text_.length(), select);
-}
-
-bool TextfieldViewsModel::MoveCursorTo(size_t pos, bool select) {
+bool TextfieldViewsModel::MoveCursorTo(const gfx::Point& point, bool select) {
if (HasCompositionText())
ConfirmCompositionText();
- bool changed = cursor_pos_ != pos || select != HasSelection();
- cursor_pos_ = pos;
- if (!select)
- ClearSelection();
- return changed;
+ return render_text_->MoveCursorTo(point, select);
}
-gfx::Rect TextfieldViewsModel::GetSelectionBounds(const gfx::Font& font) const {
- if (!HasSelection())
- return gfx::Rect();
- size_t start = std::min(selection_start_, cursor_pos_);
- size_t end = std::max(selection_start_, cursor_pos_);
- int start_x = font.GetStringWidth(text_.substr(0, start));
- int end_x = font.GetStringWidth(text_.substr(0, end));
- return gfx::Rect(start_x, 0, end_x - start_x, font.GetHeight());
+std::vector<gfx::Rect> TextfieldViewsModel::GetSelectionBounds() const {
+ return render_text_->GetSubstringBounds(render_text_->GetSelection());
}
string16 TextfieldViewsModel::GetSelectedText() const {
- return text_.substr(
- std::min(cursor_pos_, selection_start_),
- std::abs(static_cast<long>(cursor_pos_ - selection_start_)));
+ ui::Range selection = render_text_->GetSelection();
+ return GetText().substr(selection.GetMin(), selection.length());
}
void TextfieldViewsModel::GetSelectedRange(ui::Range* range) const {
- *range = ui::Range(selection_start_, cursor_pos_);
+ *range = render_text_->GetSelection();
}
void TextfieldViewsModel::SelectRange(const ui::Range& range) {
if (HasCompositionText())
ConfirmCompositionText();
- selection_start_ = GetSafePosition(range.start());
- cursor_pos_ = GetSafePosition(range.end());
+ render_text_->SetSelection(range);
}
void TextfieldViewsModel::SelectAll() {
if (HasCompositionText())
ConfirmCompositionText();
- // SelectAll selects towards the end.
- cursor_pos_ = text_.length();
- selection_start_ = 0;
+ render_text_->SelectAll();
}
void TextfieldViewsModel::SelectWord() {
if (HasCompositionText())
ConfirmCompositionText();
- // First we setup selection_start_ and cursor_pos_. There are so many cases
- // because we try to emulate what select-word looks like in a gtk textfield.
- // See associated testcase for different cases.
- if (cursor_pos_ > 0 && cursor_pos_ < text_.length()) {
- if (isalnum(text_[cursor_pos_])) {
- selection_start_ = cursor_pos_;
- cursor_pos_++;
- } else
- selection_start_ = cursor_pos_ - 1;
- } else if (cursor_pos_ == 0) {
- selection_start_ = cursor_pos_;
- if (text_.length() > 0)
- cursor_pos_++;
- } else {
- selection_start_ = cursor_pos_ - 1;
- }
-
- // Now we move selection_start_ to beginning of selection. Selection boundary
- // is defined as the position where we have alpha-num character on one side
- // and non-alpha-num char on the other side.
- for (; selection_start_ > 0; selection_start_--) {
- if (IsPositionAtWordSelectionBoundary(selection_start_))
- break;
- }
-
- // Now we move cursor_pos_ to end of selection. Selection boundary
- // is defined as the position where we have alpha-num character on one side
- // and non-alpha-num char on the other side.
- for (; cursor_pos_ < text_.length(); cursor_pos_++) {
- if (IsPositionAtWordSelectionBoundary(cursor_pos_))
- break;
- }
+ render_text_->SelectWord();
}
void TextfieldViewsModel::ClearSelection() {
if (HasCompositionText())
ConfirmCompositionText();
- selection_start_ = cursor_pos_;
+ render_text_->ClearSelection();
}
bool TextfieldViewsModel::CanUndo() {
@@ -723,8 +451,8 @@ bool TextfieldViewsModel::Undo() {
if (HasCompositionText()) // safe guard for release build.
CancelCompositionText();
- string16 old = text_;
- size_t old_cursor = cursor_pos_;
+ string16 old = GetText();
+ size_t old_cursor = render_text_->GetCursor();
(*current_edit_)->Commit();
(*current_edit_)->Undo(this);
@@ -732,7 +460,7 @@ bool TextfieldViewsModel::Undo() {
current_edit_ = edit_history_.end();
else
current_edit_--;
- return old != text_ || old_cursor != cursor_pos_;
+ return old != GetText() || old_cursor != render_text_->GetCursor();
}
bool TextfieldViewsModel::Redo() {
@@ -746,10 +474,14 @@ bool TextfieldViewsModel::Redo() {
current_edit_ = edit_history_.begin();
else
current_edit_ ++;
- string16 old = text_;
- size_t old_cursor = cursor_pos_;
+ string16 old = GetText();
+ size_t old_cursor = render_text_->GetCursor();
(*current_edit_)->Redo(this);
- return old != text_ || old_cursor != cursor_pos_;
+ return old != GetText() || old_cursor != render_text_->GetCursor();
+}
+
+string16 TextfieldViewsModel::GetVisibleText() const {
+ return GetVisibleText(0U, GetText().length());
}
bool TextfieldViewsModel::Cut() {
@@ -761,7 +493,8 @@ bool TextfieldViewsModel::Cut() {
// than beginning, unlike Delete/Backspace.
// TODO(oshima): Change Delete/Backspace to use DeleteSelection,
// update DeleteEdit and remove this trick.
- std::swap(cursor_pos_, selection_start_);
+ ui::Range selection = render_text_->GetSelection();
+ render_text_->SetSelection(ui::Range(selection.end(), selection.start()));
oshima 2011/07/23 09:51:12 doesn't range have a method to swap position?
msw 2011/07/25 05:09:54 Not that I see.
DeleteSelection();
return true;
}
@@ -787,13 +520,14 @@ bool TextfieldViewsModel::Paste() {
}
bool TextfieldViewsModel::HasSelection() const {
- return selection_start_ != cursor_pos_;
+ return !render_text_->GetSelection().is_empty();
}
void TextfieldViewsModel::DeleteSelection() {
DCHECK(!HasCompositionText());
DCHECK(HasSelection());
- ExecuteAndRecordDelete(selection_start_, cursor_pos_, false);
+ ui::Range selection = render_text_->GetSelection();
+ ExecuteAndRecordDelete(selection.start(), selection.end(), false);
}
void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
@@ -801,26 +535,24 @@ void TextfieldViewsModel::DeleteSelectionAndInsertTextAt(
if (HasCompositionText())
CancelCompositionText();
ExecuteAndRecordReplace(DO_NOT_MERGE,
- cursor_pos_,
+ render_text_->GetCursor(),
position + text.length(),
text,
position);
}
string16 TextfieldViewsModel::GetTextFromRange(const ui::Range& range) const {
- if (range.IsValid() && range.GetMin() < text_.length())
- return text_.substr(range.GetMin(), range.length());
+ if (range.IsValid() && range.GetMin() < GetText().length())
+ return GetText().substr(range.GetMin(), range.length());
return string16();
}
void TextfieldViewsModel::GetTextRange(ui::Range* range) const {
- *range = ui::Range(0, text_.length());
+ *range = ui::Range(0, GetText().length());
}
void TextfieldViewsModel::SetCompositionText(
const ui::CompositionText& composition) {
- static const TextStyle* composition_style = CreateUnderlineStyle();
-
if (HasCompositionText())
CancelCompositionText();
else if (HasSelection())
@@ -829,95 +561,55 @@ void TextfieldViewsModel::SetCompositionText(
if (composition.text.empty())
return;
- size_t length = composition.text.length();
- text_.insert(cursor_pos_, composition.text);
- composition_start_ = cursor_pos_;
- composition_end_ = composition_start_ + length;
- for (ui::CompositionUnderlines::const_iterator iter =
- composition.underlines.begin();
- iter != composition.underlines.end();
- iter++) {
- size_t start = composition_start_ + iter->start_offset;
- size_t end = composition_start_ + iter->end_offset;
- InsertStyle(&composition_style_ranges_,
- new TextStyleRange(composition_style, start, end));
- }
- std::sort(composition_style_ranges_.begin(),
- composition_style_ranges_.end(), TextStyleRangeComparator);
-
- if (composition.selection.IsValid()) {
- selection_start_ =
- std::min(composition_start_ + composition.selection.start(),
- composition_end_);
- cursor_pos_ =
- std::min(composition_start_ + composition.selection.end(),
- composition_end_);
- } else {
- cursor_pos_ = composition_end_;
- ClearSelection();
- }
+ size_t cursor = render_text_->GetCursor();
+ string16 new_text = GetText();
+ render_text_->SetText(new_text.insert(cursor, composition.text));
+ ui::Range range(cursor, cursor + composition.text.length());
+ render_text_->SetCompositionRange(range);
+ // TODO(msw): Support multiple composition underline ranges.
+
+ if (composition.selection.IsValid())
+ render_text_->SetSelection(ui::Range(
+ std::min(range.start() + composition.selection.start(), range.end()),
+ std::min(range.start() + composition.selection.end(), range.end())));
+ else
+ render_text_->SetCursor(range.end());
}
void TextfieldViewsModel::ConfirmCompositionText() {
DCHECK(HasCompositionText());
- string16 new_text =
- text_.substr(composition_start_, composition_end_ - composition_start_);
+ ui::Range range = render_text_->GetCompositionRange();
+ string16 text = GetText().substr(range.start(), range.length());
// TODO(oshima): current behavior on ChromeOS is a bit weird and not
// sure exactly how this should work. Find out and fix if necessary.
- AddOrMergeEditHistory(new InsertEdit(false, new_text, composition_start_));
- cursor_pos_ = composition_end_;
+ AddOrMergeEditHistory(new InsertEdit(false, text, range.start()));
+ render_text_->SetCursor(range.end());
ClearComposition();
- ClearSelection();
if (delegate_)
delegate_->OnCompositionTextConfirmedOrCleared();
}
void TextfieldViewsModel::CancelCompositionText() {
DCHECK(HasCompositionText());
- text_.erase(composition_start_, composition_end_ - composition_start_);
- cursor_pos_ = composition_start_;
+ ui::Range range = render_text_->GetCompositionRange();
+ string16 new_text = GetText();
+ render_text_->SetText(new_text.erase(range.start(), range.length()));
+ render_text_->SetCursor(range.start());
ClearComposition();
- ClearSelection();
if (delegate_)
delegate_->OnCompositionTextConfirmedOrCleared();
}
void TextfieldViewsModel::ClearComposition() {
- composition_start_ = composition_end_ = string16::npos;
- STLDeleteContainerPointers(composition_style_ranges_.begin(),
- composition_style_ranges_.end());
- composition_style_ranges_.clear();
-}
-
-void TextfieldViewsModel::ApplyTextStyle(const TextStyle* style,
- const ui::Range& range) {
- TextStyleRange* new_text_style_range = range.is_reversed() ?
- new TextStyleRange(style, ui::Range(range.end(), range.start())) :
- new TextStyleRange(style, range);
- InsertStyle(&style_ranges_, new_text_style_range);
- sort_style_ranges_ = true;
+ render_text_->SetCompositionRange(ui::Range::InvalidRange());
}
void TextfieldViewsModel::GetCompositionTextRange(ui::Range* range) const {
- if (HasCompositionText())
- *range = ui::Range(composition_start_, composition_end_);
- else
- *range = ui::Range::InvalidRange();
+ *range = ui::Range(render_text_->GetCompositionRange());
}
bool TextfieldViewsModel::HasCompositionText() const {
- return composition_start_ != composition_end_;
-}
-
-TextStyle* TextfieldViewsModel::CreateTextStyle() {
- TextStyle* style = new TextStyle();
- text_styles_.push_back(style);
- return style;
-}
-
-void TextfieldViewsModel::ClearAllTextStyles() {
- STLDeleteContainerPointers(style_ranges_.begin(), style_ranges_.end());
- style_ranges_.clear();
+ return !render_text_->GetCompositionRange().is_empty();
}
/////////////////////////////////////////////////////////////////
@@ -927,19 +619,7 @@ string16 TextfieldViewsModel::GetVisibleText(size_t begin, size_t end) const {
DCHECK(end >= begin);
if (is_password_)
return string16(end - begin, '*');
- return text_.substr(begin, end - begin);
-}
-
-bool TextfieldViewsModel::IsPositionAtWordSelectionBoundary(size_t pos) {
- return (isalnum(text_[pos - 1]) && !isalnum(text_[pos])) ||
- (!isalnum(text_[pos - 1]) && isalnum(text_[pos]));
-}
-
-size_t TextfieldViewsModel::GetSafePosition(size_t position) const {
- if (position > text_.length()) {
- return text_.length();
- }
- return position;
+ return GetText().substr(begin, end - begin);
}
void TextfieldViewsModel::InsertTextInternal(const string16& text,
@@ -959,8 +639,10 @@ void TextfieldViewsModel::ReplaceTextInternal(const string16& text,
bool mergeable) {
if (HasCompositionText())
CancelCompositionText();
- else if (!HasSelection())
- SelectRange(ui::Range(cursor_pos_ + text.length(), cursor_pos_));
+ else if (!HasSelection()) {
oshima 2011/07/23 09:51:12 you need {} for the 1st if, i believe. check style
msw 2011/07/25 05:09:54 Done.
+ size_t cursor = render_text_->GetCursor();
+ render_text_->SetSelection(ui::Range(cursor + text.length(), cursor));
+ }
// Edit history is recorded in InsertText.
InsertTextInternal(text, mergeable);
}
@@ -989,7 +671,7 @@ void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from,
size_t to,
bool mergeable) {
size_t old_text_start = std::min(from, to);
- const string16 text = text_.substr(old_text_start,
+ const string16 text = GetText().substr(old_text_start,
std::abs(static_cast<long>(from - to)));
bool backward = from > to;
Edit* edit = new DeleteEdit(mergeable, text, old_text_start, backward);
@@ -1001,10 +683,10 @@ void TextfieldViewsModel::ExecuteAndRecordDelete(size_t from,
void TextfieldViewsModel::ExecuteAndRecordReplaceSelection(
MergeType merge_type, const string16& new_text) {
- size_t new_text_start = std::min(cursor_pos_, selection_start_);
+ size_t new_text_start = render_text_->GetSelection().GetMin();
size_t new_cursor_pos = new_text_start + new_text.length();
ExecuteAndRecordReplace(merge_type,
- cursor_pos_,
+ render_text_->GetCursor(),
new_cursor_pos,
new_text,
new_text_start);
@@ -1015,8 +697,8 @@ void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
size_t new_cursor_pos,
const string16& new_text,
size_t new_text_start) {
- size_t old_text_start = std::min(cursor_pos_, selection_start_);
- bool backward = selection_start_ > cursor_pos_;
+ size_t old_text_start = render_text_->GetSelection().GetMin();
+ bool backward = render_text_->GetSelection().is_reversed();
Edit* edit = new ReplaceEdit(merge_type,
GetSelectedText(),
old_cursor_pos,
@@ -1033,7 +715,7 @@ void TextfieldViewsModel::ExecuteAndRecordReplace(MergeType merge_type,
void TextfieldViewsModel::ExecuteAndRecordInsert(const string16& text,
bool mergeable) {
- Edit* edit = new InsertEdit(mergeable, text, cursor_pos_);
+ Edit* edit = new InsertEdit(mergeable, text, render_text_->GetCursor());
bool delete_edit = AddOrMergeEditHistory(edit);
edit->Redo(this);
if (delete_edit)
@@ -1067,21 +749,14 @@ void TextfieldViewsModel::ModifyText(size_t delete_from,
size_t new_text_insert_at,
size_t new_cursor_pos) {
DCHECK_LE(delete_from, delete_to);
+ string16 text = GetText();
if (delete_from != delete_to)
- text_.erase(delete_from, delete_to - delete_from);
+ render_text_->SetText(text.erase(delete_from, delete_to - delete_from));
if (!new_text.empty())
- text_.insert(new_text_insert_at, new_text);
- cursor_pos_ = new_cursor_pos;
- ClearSelection();
+ render_text_->SetText(text.insert(new_text_insert_at, new_text));
+ render_text_->SetCursor(new_cursor_pos);
// TODO(oshima): mac selects the text that is just undone (but gtk doesn't).
// This looks fine feature and we may want to do the same.
}
-// static
-TextStyle* TextfieldViewsModel::CreateUnderlineStyle() {
- TextStyle* style = new TextStyle();
- style->set_underline(true);
- return style;
-}
-
} // namespace views

Powered by Google App Engine
This is Rietveld 408576698