| 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 |