OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/i18n/break_iterator.h" | 9 #include "base/i18n/break_iterator.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 | 80 |
81 StyleRange::StyleRange() | 81 StyleRange::StyleRange() |
82 : font(), | 82 : font(), |
83 foreground(SK_ColorBLACK), | 83 foreground(SK_ColorBLACK), |
84 strike(false), | 84 strike(false), |
85 underline(false), | 85 underline(false), |
86 range() { | 86 range() { |
87 } | 87 } |
88 | 88 |
89 SelectionModel::SelectionModel() { | 89 SelectionModel::SelectionModel() { |
90 Init(0, 0, 0, PREVIOUS_GRAPHEME_TRAILING); | 90 Init(0, 0, 0, LEADING); |
91 } | 91 } |
92 | 92 |
93 SelectionModel::SelectionModel(size_t pos) { | 93 SelectionModel::SelectionModel(size_t pos) { |
94 Init(pos, pos, pos, PREVIOUS_GRAPHEME_TRAILING); | 94 Init(pos, pos, pos, LEADING); |
| 95 } |
| 96 |
| 97 SelectionModel::SelectionModel(size_t start, size_t end) { |
| 98 Init(start, end, end, LEADING); |
95 } | 99 } |
96 | 100 |
97 SelectionModel::SelectionModel(size_t end, | 101 SelectionModel::SelectionModel(size_t end, |
98 size_t pos, | 102 size_t pos, |
99 CaretPlacement placement) { | 103 CaretPlacement placement) { |
100 Init(end, end, pos, placement); | 104 Init(end, end, pos, placement); |
101 } | 105 } |
102 | 106 |
103 SelectionModel::SelectionModel(size_t start, | 107 SelectionModel::SelectionModel(size_t start, |
104 size_t end, | 108 size_t end, |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 sel.set_selection_start(GetCursorPosition()); | 261 sel.set_selection_start(GetCursorPosition()); |
258 SetSelectionModel(sel); | 262 SetSelectionModel(sel); |
259 } | 263 } |
260 | 264 |
261 void RenderText::SelectAll() { | 265 void RenderText::SelectAll() { |
262 SelectionModel sel(0, text().length(), | 266 SelectionModel sel(0, text().length(), |
263 text().length(), SelectionModel::LEADING); | 267 text().length(), SelectionModel::LEADING); |
264 SetSelectionModel(sel); | 268 SetSelectionModel(sel); |
265 } | 269 } |
266 | 270 |
| 271 // TODO(xji): it does not work for languages do not use space as word breaker, |
| 272 // such as Chinese. Should use BreakIterator. |
267 void RenderText::SelectWord() { | 273 void RenderText::SelectWord() { |
268 size_t selection_start = GetSelectionStart(); | 274 size_t selection_start = GetSelectionStart(); |
269 size_t cursor_position = GetCursorPosition(); | 275 size_t cursor_position = GetCursorPosition(); |
270 // First we setup selection_start_ and selection_end_. There are so many cases | 276 // First we setup selection_start_ and selection_end_. There are so many cases |
271 // because we try to emulate what select-word looks like in a gtk textfield. | 277 // because we try to emulate what select-word looks like in a gtk textfield. |
272 // See associated testcase for different cases. | 278 // See associated testcase for different cases. |
273 if (cursor_position > 0 && cursor_position < text().length()) { | 279 if (cursor_position > 0 && cursor_position < text().length()) { |
274 if (u_isalnum(text()[cursor_position])) { | 280 if (u_isalnum(text()[cursor_position])) { |
275 selection_start = cursor_position; | 281 selection_start = cursor_position; |
276 cursor_position++; | 282 cursor_position++; |
(...skipping 19 matching lines...) Expand all Loading... |
296 // is defined as the position where we have alpha-num character on one side | 302 // is defined as the position where we have alpha-num character on one side |
297 // and non-alpha-num char on the other side. | 303 // and non-alpha-num char on the other side. |
298 for (; cursor_position < text().length(); cursor_position++) { | 304 for (; cursor_position < text().length(); cursor_position++) { |
299 if (IsPositionAtWordSelectionBoundary(cursor_position)) | 305 if (IsPositionAtWordSelectionBoundary(cursor_position)) |
300 break; | 306 break; |
301 } | 307 } |
302 | 308 |
303 SelectionModel sel(selection_model()); | 309 SelectionModel sel(selection_model()); |
304 sel.set_selection_start(selection_start); | 310 sel.set_selection_start(selection_start); |
305 sel.set_selection_end(cursor_position); | 311 sel.set_selection_end(cursor_position); |
306 sel.set_caret_placement(SelectionModel::PREVIOUS_GRAPHEME_TRAILING); | 312 sel.set_caret_pos(GetIndexOfPreviousGrapheme(cursor_position)); |
| 313 sel.set_caret_placement(SelectionModel::TRAILING); |
307 SetSelectionModel(sel); | 314 SetSelectionModel(sel); |
308 } | 315 } |
309 | 316 |
310 const ui::Range& RenderText::GetCompositionRange() const { | 317 const ui::Range& RenderText::GetCompositionRange() const { |
311 return composition_range_; | 318 return composition_range_; |
312 } | 319 } |
313 | 320 |
314 void RenderText::SetCompositionRange(const ui::Range& composition_range) { | 321 void RenderText::SetCompositionRange(const ui::Range& composition_range) { |
315 CHECK(!composition_range.IsValid() || | 322 CHECK(!composition_range.IsValid() || |
316 ui::Range(0, text_.length()).Contains(composition_range)); | 323 ui::Range(0, text_.length()).Contains(composition_range)); |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 if (!success) | 552 if (!success) |
546 return current; | 553 return current; |
547 while (iter.Advance()) { | 554 while (iter.Advance()) { |
548 pos = iter.pos(); | 555 pos = iter.pos(); |
549 if (iter.IsWord() && pos > current.selection_end()) | 556 if (iter.IsWord() && pos > current.selection_end()) |
550 break; | 557 break; |
551 } | 558 } |
552 return SelectionModel(pos, pos, SelectionModel::LEADING); | 559 return SelectionModel(pos, pos, SelectionModel::LEADING); |
553 } | 560 } |
554 | 561 |
555 size_t RenderText::GetIndexOfPreviousGrapheme(size_t position) const { | 562 size_t RenderText::GetIndexOfPreviousGrapheme(size_t position) { |
556 // TODO(msw): Handle complex script. | 563 // TODO(msw): Handle complex script. |
557 return std::max(static_cast<int>(position - 1), static_cast<int>(0)); | 564 return std::max(static_cast<int>(position - 1), static_cast<int>(0)); |
558 } | 565 } |
559 | 566 |
560 void RenderText::ApplyCompositionAndSelectionStyles( | 567 void RenderText::ApplyCompositionAndSelectionStyles( |
561 StyleRanges* style_ranges) const { | 568 StyleRanges* style_ranges) const { |
562 // TODO(msw): This pattern ought to be reconsidered; what about composition | 569 // TODO(msw): This pattern ought to be reconsidered; what about composition |
563 // and selection overlaps, retain existing local style features? | 570 // and selection overlaps, retain existing local style features? |
564 // Apply a composition style override to a copy of the style ranges. | 571 // Apply a composition style override to a copy of the style ranges. |
565 if (composition_range_.IsValid() && !composition_range_.is_empty()) { | 572 if (composition_range_.IsValid() && !composition_range_.is_empty()) { |
(...skipping 29 matching lines...) Expand all Loading... |
595 } else if ((display_offset_.x() + cursor_bounds_.right()) > display_width) { | 602 } else if ((display_offset_.x() + cursor_bounds_.right()) > display_width) { |
596 // Pan to show the cursor when it overflows to the right, | 603 // Pan to show the cursor when it overflows to the right, |
597 display_offset_.set_x(display_width - cursor_bounds_.right()); | 604 display_offset_.set_x(display_width - cursor_bounds_.right()); |
598 } else if ((display_offset_.x() + cursor_bounds_.x()) < 0) { | 605 } else if ((display_offset_.x() + cursor_bounds_.x()) < 0) { |
599 // Pan to show the cursor when it overflows to the left. | 606 // Pan to show the cursor when it overflows to the left. |
600 display_offset_.set_x(-cursor_bounds_.x()); | 607 display_offset_.set_x(-cursor_bounds_.x()); |
601 } | 608 } |
602 } | 609 } |
603 | 610 |
604 } // namespace gfx | 611 } // namespace gfx |
OLD | NEW |