| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/string16.h" | 10 #include "base/string16.h" |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 EXPECT_STR_EQ("E", model.GetSelectedText()); | 269 EXPECT_STR_EQ("E", model.GetSelectedText()); |
| 270 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); | 270 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); |
| 271 EXPECT_STR_EQ("EL", model.GetSelectedText()); | 271 EXPECT_STR_EQ("EL", model.GetSelectedText()); |
| 272 | 272 |
| 273 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true); | 273 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, true); |
| 274 EXPECT_STR_EQ("H", model.GetSelectedText()); | 274 EXPECT_STR_EQ("H", model.GetSelectedText()); |
| 275 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, true); | 275 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, true); |
| 276 EXPECT_STR_EQ("ELLO", model.GetSelectedText()); | 276 EXPECT_STR_EQ("ELLO", model.GetSelectedText()); |
| 277 model.ClearSelection(); | 277 model.ClearSelection(); |
| 278 EXPECT_EQ(string16(), model.GetSelectedText()); | 278 EXPECT_EQ(string16(), model.GetSelectedText()); |
| 279 model.SelectAll(); | 279 |
| 280 // SelectAll(false) selects towards the end. |
| 281 model.SelectAll(false); |
| 280 EXPECT_STR_EQ("HELLO", model.GetSelectedText()); | 282 EXPECT_STR_EQ("HELLO", model.GetSelectedText()); |
| 281 // SelectAll should select towards the end. | |
| 282 gfx::SelectionModel sel; | 283 gfx::SelectionModel sel; |
| 283 model.GetSelectionModel(&sel); | 284 model.GetSelectionModel(&sel); |
| 284 EXPECT_EQ(ui::Range(0, 5), sel.selection()); | 285 EXPECT_EQ(ui::Range(0, 5), sel.selection()); |
| 285 | 286 |
| 287 // SelectAll(true) selects towards the beginning. |
| 288 model.SelectAll(true); |
| 289 EXPECT_STR_EQ("HELLO", model.GetSelectedText()); |
| 290 model.GetSelectionModel(&sel); |
| 291 EXPECT_EQ(ui::Range(5, 0), sel.selection()); |
| 292 |
| 286 // Select and move cursor | 293 // Select and move cursor |
| 287 model.SelectRange(ui::Range(1U, 3U)); | 294 model.SelectRange(ui::Range(1U, 3U)); |
| 288 EXPECT_STR_EQ("EL", model.GetSelectedText()); | 295 EXPECT_STR_EQ("EL", model.GetSelectedText()); |
| 289 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); | 296 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); |
| 290 EXPECT_EQ(1U, model.GetCursorPosition()); | 297 EXPECT_EQ(1U, model.GetCursorPosition()); |
| 291 model.SelectRange(ui::Range(1U, 3U)); | 298 model.SelectRange(ui::Range(1U, 3U)); |
| 292 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); | 299 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); |
| 293 EXPECT_EQ(3U, model.GetCursorPosition()); | 300 EXPECT_EQ(3U, model.GetCursorPosition()); |
| 294 | 301 |
| 295 // Select all and move cursor | 302 // Select all and move cursor |
| 296 model.SelectAll(); | 303 model.SelectAll(false); |
| 297 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); | 304 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false); |
| 298 EXPECT_EQ(0U, model.GetCursorPosition()); | 305 EXPECT_EQ(0U, model.GetCursorPosition()); |
| 299 model.SelectAll(); | 306 model.SelectAll(false); |
| 300 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); | 307 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); |
| 301 EXPECT_EQ(5U, model.GetCursorPosition()); | 308 EXPECT_EQ(5U, model.GetCursorPosition()); |
| 302 } | 309 } |
| 303 | 310 |
| 304 TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { | 311 TEST_F(TextfieldViewsModelTest, Selection_BidiWithNonSpacingMarks) { |
| 305 // Selection is a logical operation. And it should work with the arrow | 312 // Selection is a logical operation. And it should work with the arrow |
| 306 // keys doing visual movements, while the selection is logical between | 313 // keys doing visual movements, while the selection is logical between |
| 307 // the (logical) start and end points. Selection is simply defined as | 314 // the (logical) start and end points. Selection is simply defined as |
| 308 // the portion of text between the logical positions of the start and end | 315 // the portion of text between the logical positions of the start and end |
| 309 // caret positions. | 316 // caret positions. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 330 EXPECT_EQ(ui::Range(2, 3), model.render_text()->selection()); | 337 EXPECT_EQ(ui::Range(2, 3), model.render_text()->selection()); |
| 331 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); | 338 EXPECT_EQ(WideToUTF16(L"c"), model.GetSelectedText()); |
| 332 | 339 |
| 333 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); | 340 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); |
| 334 EXPECT_EQ(ui::Range(2, 10), model.render_text()->selection()); | 341 EXPECT_EQ(ui::Range(2, 10), model.render_text()->selection()); |
| 335 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"d"), | 342 EXPECT_EQ(WideToUTF16(L"c\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"d"), |
| 336 model.GetSelectedText()); | 343 model.GetSelectedText()); |
| 337 | 344 |
| 338 model.ClearSelection(); | 345 model.ClearSelection(); |
| 339 EXPECT_EQ(string16(), model.GetSelectedText()); | 346 EXPECT_EQ(string16(), model.GetSelectedText()); |
| 340 model.SelectAll(); | 347 model.SelectAll(false); |
| 341 EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"), | 348 EXPECT_EQ(WideToUTF16(L"abc\x05E9\x05BC\x05C1\x05B8\x05E0\x05B8"L"def"), |
| 342 model.GetSelectedText()); | 349 model.GetSelectedText()); |
| 343 #endif | 350 #endif |
| 344 | 351 |
| 345 // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is | 352 // In case of "aBc", this test shows how to select "aB" or "Bc", assume 'B' is |
| 346 // an RTL character. | 353 // an RTL character. |
| 347 model.SetText(WideToUTF16(L"a\x05E9"L"b")); | 354 model.SetText(WideToUTF16(L"a\x05E9"L"b")); |
| 348 MoveCursorTo(model, 0); | 355 MoveCursorTo(model, 0); |
| 349 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); | 356 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); |
| 350 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText()); | 357 EXPECT_EQ(WideToUTF16(L"a"), model.GetSelectedText()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 373 EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText()); | 380 EXPECT_EQ(WideToUTF16(L"a\x05E9"), model.GetSelectedText()); |
| 374 | 381 |
| 375 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); | 382 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); |
| 376 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); | 383 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); |
| 377 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); | 384 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true); |
| 378 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); | 385 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); |
| 379 EXPECT_EQ(WideToUTF16(L"\x05E9"L"b"), model.GetSelectedText()); | 386 EXPECT_EQ(WideToUTF16(L"\x05E9"L"b"), model.GetSelectedText()); |
| 380 | 387 |
| 381 model.ClearSelection(); | 388 model.ClearSelection(); |
| 382 EXPECT_EQ(string16(), model.GetSelectedText()); | 389 EXPECT_EQ(string16(), model.GetSelectedText()); |
| 383 model.SelectAll(); | 390 model.SelectAll(false); |
| 384 EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); | 391 EXPECT_EQ(WideToUTF16(L"a\x05E9"L"b"), model.GetSelectedText()); |
| 385 } | 392 } |
| 386 | 393 |
| 387 TEST_F(TextfieldViewsModelTest, SelectionAndEdit) { | 394 TEST_F(TextfieldViewsModelTest, SelectionAndEdit) { |
| 388 TextfieldViewsModel model(NULL); | 395 TextfieldViewsModel model(NULL); |
| 389 model.Append(ASCIIToUTF16("HELLO")); | 396 model.Append(ASCIIToUTF16("HELLO")); |
| 390 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); | 397 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false); |
| 391 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); | 398 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); |
| 392 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "EL" | 399 model.MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true); // "EL" |
| 393 EXPECT_TRUE(model.Backspace()); | 400 EXPECT_TRUE(model.Backspace()); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 461 } | 468 } |
| 462 | 469 |
| 463 TEST_F(TextfieldViewsModelTest, SetText) { | 470 TEST_F(TextfieldViewsModelTest, SetText) { |
| 464 TextfieldViewsModel model(NULL); | 471 TextfieldViewsModel model(NULL); |
| 465 model.Append(ASCIIToUTF16("HELLO")); | 472 model.Append(ASCIIToUTF16("HELLO")); |
| 466 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); | 473 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); |
| 467 model.SetText(ASCIIToUTF16("GOODBYE")); | 474 model.SetText(ASCIIToUTF16("GOODBYE")); |
| 468 EXPECT_STR_EQ("GOODBYE", model.GetText()); | 475 EXPECT_STR_EQ("GOODBYE", model.GetText()); |
| 469 // SetText move the cursor to the end of the new text. | 476 // SetText move the cursor to the end of the new text. |
| 470 EXPECT_EQ(7U, model.GetCursorPosition()); | 477 EXPECT_EQ(7U, model.GetCursorPosition()); |
| 471 model.SelectAll(); | 478 model.SelectAll(false); |
| 472 EXPECT_STR_EQ("GOODBYE", model.GetSelectedText()); | 479 EXPECT_STR_EQ("GOODBYE", model.GetSelectedText()); |
| 473 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); | 480 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); |
| 474 EXPECT_EQ(7U, model.GetCursorPosition()); | 481 EXPECT_EQ(7U, model.GetCursorPosition()); |
| 475 | 482 |
| 476 model.SetText(ASCIIToUTF16("BYE")); | 483 model.SetText(ASCIIToUTF16("BYE")); |
| 477 // Setting shorter string moves the cursor to the end of the new string. | 484 // Setting shorter string moves the cursor to the end of the new string. |
| 478 EXPECT_EQ(3U, model.GetCursorPosition()); | 485 EXPECT_EQ(3U, model.GetCursorPosition()); |
| 479 EXPECT_EQ(string16(), model.GetSelectedText()); | 486 EXPECT_EQ(string16(), model.GetSelectedText()); |
| 480 model.SetText(string16()); | 487 model.SetText(string16()); |
| 481 EXPECT_EQ(0U, model.GetCursorPosition()); | 488 EXPECT_EQ(0U, model.GetCursorPosition()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 508 | 515 |
| 509 // Copy with an empty selection should do nothing. | 516 // Copy with an empty selection should do nothing. |
| 510 model.Copy(); | 517 model.Copy(); |
| 511 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 518 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
| 512 EXPECT_EQ(initial_clipboard_text, clipboard_text); | 519 EXPECT_EQ(initial_clipboard_text, clipboard_text); |
| 513 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); | 520 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); |
| 514 EXPECT_EQ(11U, model.GetCursorPosition()); | 521 EXPECT_EQ(11U, model.GetCursorPosition()); |
| 515 | 522 |
| 516 // Cut on obscured (password) text should do nothing. | 523 // Cut on obscured (password) text should do nothing. |
| 517 model.render_text()->SetObscured(true); | 524 model.render_text()->SetObscured(true); |
| 518 model.SelectAll(); | 525 model.SelectAll(false); |
| 519 EXPECT_FALSE(model.Cut()); | 526 EXPECT_FALSE(model.Cut()); |
| 520 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 527 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
| 521 EXPECT_EQ(initial_clipboard_text, clipboard_text); | 528 EXPECT_EQ(initial_clipboard_text, clipboard_text); |
| 522 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); | 529 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); |
| 523 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText()); | 530 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText()); |
| 524 | 531 |
| 525 // Copy on obscured text should do nothing. | 532 // Copy on obscured text should do nothing. |
| 526 model.SelectAll(); | 533 model.SelectAll(false); |
| 527 EXPECT_FALSE(model.Copy()); | 534 EXPECT_FALSE(model.Copy()); |
| 528 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 535 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
| 529 EXPECT_EQ(initial_clipboard_text, clipboard_text); | 536 EXPECT_EQ(initial_clipboard_text, clipboard_text); |
| 530 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); | 537 EXPECT_STR_EQ("HELLO WORLD", model.GetText()); |
| 531 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText()); | 538 EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText()); |
| 532 | 539 |
| 533 // Cut with non-empty selection. | 540 // Cut with non-empty selection. |
| 534 model.render_text()->SetObscured(false); | 541 model.render_text()->SetObscured(false); |
| 535 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); | 542 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); |
| 536 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); | 543 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); |
| 537 EXPECT_TRUE(model.Cut()); | 544 EXPECT_TRUE(model.Cut()); |
| 538 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 545 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
| 539 EXPECT_STR_EQ("WORLD", clipboard_text); | 546 EXPECT_STR_EQ("WORLD", clipboard_text); |
| 540 EXPECT_STR_EQ("HELLO ", model.GetText()); | 547 EXPECT_STR_EQ("HELLO ", model.GetText()); |
| 541 EXPECT_EQ(6U, model.GetCursorPosition()); | 548 EXPECT_EQ(6U, model.GetCursorPosition()); |
| 542 | 549 |
| 543 // Copy with non-empty selection. | 550 // Copy with non-empty selection. |
| 544 model.Append(ASCIIToUTF16("HELLO WORLD")); | 551 model.Append(ASCIIToUTF16("HELLO WORLD")); |
| 545 model.SelectAll(); | 552 model.SelectAll(false); |
| 546 model.Copy(); | 553 model.Copy(); |
| 547 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); | 554 clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text); |
| 548 EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text); | 555 EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text); |
| 549 EXPECT_STR_EQ("HELLO HELLO WORLD", model.GetText()); | 556 EXPECT_STR_EQ("HELLO HELLO WORLD", model.GetText()); |
| 550 EXPECT_EQ(17U, model.GetCursorPosition()); | 557 EXPECT_EQ(17U, model.GetCursorPosition()); |
| 551 | 558 |
| 552 // Test for paste. | 559 // Test for paste. |
| 553 model.ClearSelection(); | 560 model.ClearSelection(); |
| 554 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); | 561 model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, false); |
| 555 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); | 562 model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true); |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 968 composition_text_confirmed_or_cleared_ = false; | 975 composition_text_confirmed_or_cleared_ = false; |
| 969 EXPECT_STR_EQ("678678", model.GetText()); | 976 EXPECT_STR_EQ("678678", model.GetText()); |
| 970 | 977 |
| 971 model.SetCompositionText(composition); | 978 model.SetCompositionText(composition); |
| 972 model.SelectRange(ui::Range(0, 3)); | 979 model.SelectRange(ui::Range(0, 3)); |
| 973 EXPECT_TRUE(composition_text_confirmed_or_cleared_); | 980 EXPECT_TRUE(composition_text_confirmed_or_cleared_); |
| 974 composition_text_confirmed_or_cleared_ = false; | 981 composition_text_confirmed_or_cleared_ = false; |
| 975 EXPECT_STR_EQ("678", model.GetText()); | 982 EXPECT_STR_EQ("678", model.GetText()); |
| 976 | 983 |
| 977 model.SetCompositionText(composition); | 984 model.SetCompositionText(composition); |
| 978 model.SelectAll(); | 985 model.SelectAll(false); |
| 979 EXPECT_TRUE(composition_text_confirmed_or_cleared_); | 986 EXPECT_TRUE(composition_text_confirmed_or_cleared_); |
| 980 composition_text_confirmed_or_cleared_ = false; | 987 composition_text_confirmed_or_cleared_ = false; |
| 981 EXPECT_STR_EQ("678", model.GetText()); | 988 EXPECT_STR_EQ("678", model.GetText()); |
| 982 | 989 |
| 983 model.SetCompositionText(composition); | 990 model.SetCompositionText(composition); |
| 984 model.SelectWord(); | 991 model.SelectWord(); |
| 985 EXPECT_TRUE(composition_text_confirmed_or_cleared_); | 992 EXPECT_TRUE(composition_text_confirmed_or_cleared_); |
| 986 composition_text_confirmed_or_cleared_ = false; | 993 composition_text_confirmed_or_cleared_ = false; |
| 987 EXPECT_STR_EQ("678", model.GetText()); | 994 EXPECT_STR_EQ("678", model.GetText()); |
| 988 | 995 |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1520 EXPECT_TRUE(model.Undo()); | 1527 EXPECT_TRUE(model.Undo()); |
| 1521 EXPECT_STR_EQ("ABCDE", model.GetText()); | 1528 EXPECT_STR_EQ("ABCDE", model.GetText()); |
| 1522 EXPECT_TRUE(model.Redo()); | 1529 EXPECT_TRUE(model.Redo()); |
| 1523 EXPECT_STR_EQ("1234", model.GetText()); | 1530 EXPECT_STR_EQ("1234", model.GetText()); |
| 1524 EXPECT_FALSE(model.Redo()); | 1531 EXPECT_FALSE(model.Redo()); |
| 1525 | 1532 |
| 1526 // TODO(oshima): We need MockInputMethod to test the behavior with IME. | 1533 // TODO(oshima): We need MockInputMethod to test the behavior with IME. |
| 1527 } | 1534 } |
| 1528 | 1535 |
| 1529 } // namespace views | 1536 } // namespace views |
| OLD | NEW |