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

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

Issue 2031433002: Views::Textfield: Decouple handling of menu and text editing commands. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor2_virtual_calls
Patch Set: Address review comments. Created 4 years, 6 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 unified diff | Download patch
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | ui/views/view_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "ui/views/controls/textfield/textfield.h" 5 #include "ui/views/controls/textfield/textfield.h"
6 6
7 #include <string> 7 #include <string>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 } 241 }
242 return kNoCommand; 242 return kNoCommand;
243 } 243 }
244 #endif 244 #endif
245 245
246 const gfx::FontList& GetDefaultFontList() { 246 const gfx::FontList& GetDefaultFontList() {
247 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 247 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
248 return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta); 248 return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta);
249 } 249 }
250 250
251 // Returns true if |command_id| is a menu action installed by this textfield.
252 // Keep in sync with UpdateContextMenu.
253 bool IsMenuCommand(int command_id) {
254 switch (command_id) {
255 case IDS_APP_UNDO:
256 case IDS_APP_CUT:
257 case IDS_APP_COPY:
258 case IDS_APP_PASTE:
259 case IDS_APP_DELETE:
260 case IDS_APP_SELECT_ALL:
261 return true;
262 }
263 return false;
264 }
265
251 } // namespace 266 } // namespace
252 267
253 // static 268 // static
254 const char Textfield::kViewClassName[] = "Textfield"; 269 const char Textfield::kViewClassName[] = "Textfield";
255 const int Textfield::kTextPadding = 3; 270 const int Textfield::kTextPadding = 3;
256 271
257 // static 272 // static
258 size_t Textfield::GetCaretBlinkMs() { 273 size_t Textfield::GetCaretBlinkMs() {
259 static const size_t default_value = 500; 274 static const size_t default_value = 500;
260 #if defined(OS_WIN) 275 #if defined(OS_WIN)
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 } 578 }
564 579
565 void Textfield::ClearEditHistory() { 580 void Textfield::ClearEditHistory() {
566 model_->ClearEditHistory(); 581 model_->ClearEditHistory();
567 } 582 }
568 583
569 void Textfield::SetAccessibleName(const base::string16& name) { 584 void Textfield::SetAccessibleName(const base::string16& name) {
570 accessible_name_ = name; 585 accessible_name_ = name;
571 } 586 }
572 587
573 void Textfield::ExecuteCommand(int command_id) {
574 ExecuteCommand(command_id, ui::EF_NONE);
575 }
576
577 bool Textfield::HasTextBeingDragged() { 588 bool Textfield::HasTextBeingDragged() {
578 return initiating_drag_; 589 return initiating_drag_;
579 } 590 }
580 591
581 //////////////////////////////////////////////////////////////////////////////// 592 ////////////////////////////////////////////////////////////////////////////////
582 // Textfield, View overrides: 593 // Textfield, View overrides:
583 594
584 gfx::Insets Textfield::GetInsets() const { 595 gfx::Insets Textfield::GetInsets() const {
585 gfx::Insets insets = View::GetInsets(); 596 gfx::Insets insets = View::GetInsets();
586 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); 597 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding);
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 return handled; 721 return handled;
711 722
712 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 723 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
713 ui::TextEditKeyBindingsDelegateAuraLinux* delegate = 724 ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
714 ui::GetTextEditKeyBindingsDelegate(); 725 ui::GetTextEditKeyBindingsDelegate();
715 std::vector<ui::TextEditCommandAuraLinux> commands; 726 std::vector<ui::TextEditCommandAuraLinux> commands;
716 if (!handled && delegate && delegate->MatchEvent(event, &commands)) { 727 if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
717 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; 728 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
718 for (size_t i = 0; i < commands.size(); ++i) { 729 for (size_t i = 0; i < commands.size(); ++i) {
719 const int command = GetViewsCommand(commands[i], rtl); 730 const int command = GetViewsCommand(commands[i], rtl);
720 if (IsCommandIdEnabled(command)) { 731 if (IsEditCommandEnabled(command)) {
721 ExecuteCommand(command); 732 ExecuteEditCommand(command);
722 handled = true; 733 handled = true;
723 } 734 }
724 } 735 }
725 return handled; 736 return handled;
726 } 737 }
727 #endif 738 #endif
728 739
729 if (edit_command == kNoCommand) 740 if (edit_command == kNoCommand)
730 edit_command = GetCommandForKeyEvent(event); 741 edit_command = GetCommandForKeyEvent(event);
731 742
732 if (!handled && IsCommandIdEnabled(edit_command)) { 743 if (!handled && IsEditCommandEnabled(edit_command)) {
733 ExecuteCommand(edit_command); 744 ExecuteEditCommand(edit_command);
734 handled = true; 745 handled = true;
735 } 746 }
736 return handled; 747 return handled;
737 } 748 }
738 749
739 void Textfield::OnGestureEvent(ui::GestureEvent* event) { 750 void Textfield::OnGestureEvent(ui::GestureEvent* event) {
740 switch (event->type()) { 751 switch (event->type()) {
741 case ui::ET_GESTURE_TAP_DOWN: 752 case ui::ET_GESTURE_TAP_DOWN:
742 RequestFocus(); 753 RequestFocus();
743 ShowImeIfNeeded(); 754 ShowImeIfNeeded();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 break; 838 break;
828 default: 839 default:
829 return; 840 return;
830 } 841 }
831 } 842 }
832 843
833 // This function is called by BrowserView to execute clipboard commands. 844 // This function is called by BrowserView to execute clipboard commands.
834 bool Textfield::AcceleratorPressed(const ui::Accelerator& accelerator) { 845 bool Textfield::AcceleratorPressed(const ui::Accelerator& accelerator) {
835 ui::KeyEvent event(accelerator.type(), accelerator.key_code(), 846 ui::KeyEvent event(accelerator.type(), accelerator.key_code(),
836 accelerator.modifiers()); 847 accelerator.modifiers());
837 ExecuteCommand(GetCommandForKeyEvent(event)); 848 ExecuteEditCommand(GetCommandForKeyEvent(event));
838 return true; 849 return true;
839 } 850 }
840 851
841 bool Textfield::CanHandleAccelerators() const { 852 bool Textfield::CanHandleAccelerators() const {
842 return GetRenderText()->focused() && View::CanHandleAccelerators(); 853 return GetRenderText()->focused() && View::CanHandleAccelerators();
843 } 854 }
844 855
845 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) { 856 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
846 SelectAll(false); 857 SelectAll(false);
847 } 858 }
848 859
849 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) { 860 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
850 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 861 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
851 // Skip any accelerator handling that conflicts with custom keybindings. 862 // Skip any accelerator handling that conflicts with custom keybindings.
852 ui::TextEditKeyBindingsDelegateAuraLinux* delegate = 863 ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
853 ui::GetTextEditKeyBindingsDelegate(); 864 ui::GetTextEditKeyBindingsDelegate();
854 std::vector<ui::TextEditCommandAuraLinux> commands; 865 std::vector<ui::TextEditCommandAuraLinux> commands;
855 if (delegate && delegate->MatchEvent(event, &commands)) { 866 if (delegate && delegate->MatchEvent(event, &commands)) {
856 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; 867 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
857 for (size_t i = 0; i < commands.size(); ++i) 868 for (size_t i = 0; i < commands.size(); ++i)
858 if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl))) 869 if (IsEditCommandEnabled(GetViewsCommand(commands[i], rtl)))
859 return true; 870 return true;
860 } 871 }
861 #endif 872 #endif
862 873
863 // Skip backspace accelerator handling; editable textfields handle this key. 874 // Skip backspace accelerator handling; editable textfields handle this key.
864 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes. 875 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
865 const bool is_backspace = event.key_code() == ui::VKEY_BACK; 876 const bool is_backspace = event.key_code() == ui::VKEY_BACK;
866 return (is_backspace && !read_only()) || event.IsUnicodeKeyCode(); 877 return (is_backspace && !read_only()) || event.IsUnicodeKeyCode();
867 } 878 }
868 879
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 } 1232 }
1222 1233
1223 //////////////////////////////////////////////////////////////////////////////// 1234 ////////////////////////////////////////////////////////////////////////////////
1224 // Textfield, ui::SimpleMenuModel::Delegate overrides: 1235 // Textfield, ui::SimpleMenuModel::Delegate overrides:
1225 1236
1226 bool Textfield::IsCommandIdChecked(int command_id) const { 1237 bool Textfield::IsCommandIdChecked(int command_id) const {
1227 return true; 1238 return true;
1228 } 1239 }
1229 1240
1230 bool Textfield::IsCommandIdEnabled(int command_id) const { 1241 bool Textfield::IsCommandIdEnabled(int command_id) const {
1231 base::string16 result; 1242 return IsMenuCommand(command_id) &&
1232 bool editable = !read_only(); 1243 Textfield::IsEditCommandEnabled(command_id);
1233 bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
1234 switch (command_id) {
1235 case IDS_APP_UNDO:
1236 return editable && model_->CanUndo();
1237 case IDS_APP_REDO:
1238 return editable && model_->CanRedo();
1239 case IDS_APP_CUT:
1240 return editable && readable && model_->HasSelection();
1241 case IDS_APP_COPY:
1242 return readable && model_->HasSelection();
1243 case IDS_APP_PASTE:
1244 ui::Clipboard::GetForCurrentThread()->ReadText(
1245 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1246 return editable && !result.empty();
1247 case IDS_APP_DELETE:
1248 return editable && model_->HasSelection();
1249 case IDS_APP_SELECT_ALL:
1250 return !text().empty();
1251 case IDS_DELETE_FORWARD:
1252 case IDS_DELETE_BACKWARD:
1253 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1254 case IDS_DELETE_TO_END_OF_LINE:
1255 case IDS_DELETE_WORD_BACKWARD:
1256 case IDS_DELETE_WORD_FORWARD:
1257 return editable;
1258 case IDS_MOVE_LEFT:
1259 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1260 case IDS_MOVE_RIGHT:
1261 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1262 case IDS_MOVE_WORD_LEFT:
1263 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1264 case IDS_MOVE_WORD_RIGHT:
1265 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1266 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1267 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1268 case IDS_MOVE_TO_END_OF_LINE:
1269 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1270 return true;
1271 default:
1272 return false;
1273 }
1274 } 1244 }
1275 1245
1276 bool Textfield::GetAcceleratorForCommandId(int command_id, 1246 bool Textfield::GetAcceleratorForCommandId(int command_id,
1277 ui::Accelerator* accelerator) { 1247 ui::Accelerator* accelerator) {
1278 switch (command_id) { 1248 switch (command_id) {
1279 case IDS_APP_UNDO: 1249 case IDS_APP_UNDO:
1280 *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN); 1250 *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
1281 return true; 1251 return true;
1282 1252
1283 case IDS_APP_CUT: 1253 case IDS_APP_CUT:
(...skipping 12 matching lines...) Expand all
1296 *accelerator = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN); 1266 *accelerator = ui::Accelerator(ui::VKEY_A, ui::EF_CONTROL_DOWN);
1297 return true; 1267 return true;
1298 1268
1299 default: 1269 default:
1300 return false; 1270 return false;
1301 } 1271 }
1302 } 1272 }
1303 1273
1304 void Textfield::ExecuteCommand(int command_id, int event_flags) { 1274 void Textfield::ExecuteCommand(int command_id, int event_flags) {
1305 DestroyTouchSelection(); 1275 DestroyTouchSelection();
1306 1276 if (Textfield::IsCommandIdEnabled(command_id))
1307 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent 1277 Textfield::ExecuteEditCommand(command_id);
1308 // modifications of the command should happen here.
1309 if (HasSelection()) {
1310 switch (command_id) {
1311 case IDS_DELETE_WORD_BACKWARD:
1312 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1313 command_id = IDS_DELETE_BACKWARD;
1314 break;
1315 case IDS_DELETE_WORD_FORWARD:
1316 case IDS_DELETE_TO_END_OF_LINE:
1317 command_id = IDS_DELETE_FORWARD;
1318 break;
1319 }
1320 }
1321
1322 if (!IsCommandIdEnabled(command_id))
1323 return;
1324
1325 bool text_changed = false;
1326 bool cursor_changed = false;
1327 bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
1328 gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
1329 gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
1330 gfx::SelectionModel selection_model = GetSelectionModel();
1331
1332 OnBeforeUserAction();
1333 switch (command_id) {
1334 case IDS_APP_UNDO:
1335 text_changed = cursor_changed = model_->Undo();
1336 break;
1337 case IDS_APP_REDO:
1338 text_changed = cursor_changed = model_->Redo();
1339 break;
1340 case IDS_APP_CUT:
1341 text_changed = cursor_changed = Cut();
1342 break;
1343 case IDS_APP_COPY:
1344 Copy();
1345 break;
1346 case IDS_APP_PASTE:
1347 text_changed = cursor_changed = Paste();
1348 break;
1349 case IDS_APP_DELETE:
1350 text_changed = cursor_changed = model_->Delete();
1351 break;
1352 case IDS_APP_SELECT_ALL:
1353 SelectAll(false);
1354 break;
1355 case IDS_DELETE_BACKWARD:
1356 text_changed = cursor_changed = model_->Backspace();
1357 break;
1358 case IDS_DELETE_FORWARD:
1359 text_changed = cursor_changed = model_->Delete();
1360 break;
1361 case IDS_DELETE_TO_END_OF_LINE:
1362 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1363 text_changed = cursor_changed = model_->Delete();
1364 break;
1365 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1366 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1367 text_changed = cursor_changed = model_->Backspace();
1368 break;
1369 case IDS_DELETE_WORD_BACKWARD:
1370 model_->MoveCursor(gfx::WORD_BREAK, begin, true);
1371 text_changed = cursor_changed = model_->Backspace();
1372 break;
1373 case IDS_DELETE_WORD_FORWARD:
1374 model_->MoveCursor(gfx::WORD_BREAK, end, true);
1375 text_changed = cursor_changed = model_->Delete();
1376 break;
1377 case IDS_MOVE_LEFT:
1378 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
1379 break;
1380 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1381 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
1382 break;
1383 case IDS_MOVE_RIGHT:
1384 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
1385 break;
1386 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1387 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
1388 break;
1389 case IDS_MOVE_WORD_LEFT:
1390 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
1391 break;
1392 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1393 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
1394 break;
1395 case IDS_MOVE_WORD_RIGHT:
1396 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
1397 break;
1398 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1399 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
1400 break;
1401 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1402 model_->MoveCursor(gfx::LINE_BREAK, begin, false);
1403 break;
1404 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1405 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1406 break;
1407 case IDS_MOVE_TO_END_OF_LINE:
1408 model_->MoveCursor(gfx::LINE_BREAK, end, false);
1409 break;
1410 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1411 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1412 break;
1413 default:
1414 NOTREACHED();
1415 break;
1416 }
1417
1418 cursor_changed |= GetSelectionModel() != selection_model;
1419 if (cursor_changed)
1420 UpdateSelectionClipboard();
1421 UpdateAfterChange(text_changed, cursor_changed);
1422 OnAfterUserAction();
1423 } 1278 }
1424 1279
1425 //////////////////////////////////////////////////////////////////////////////// 1280 ////////////////////////////////////////////////////////////////////////////////
1426 // Textfield, ui::TextInputClient overrides: 1281 // Textfield, ui::TextInputClient overrides:
1427 1282
1428 void Textfield::SetCompositionText(const ui::CompositionText& composition) { 1283 void Textfield::SetCompositionText(const ui::CompositionText& composition) {
1429 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1284 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1430 return; 1285 return;
1431 1286
1432 OnBeforeUserAction(); 1287 OnBeforeUserAction();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 range.set_start(range.start() - before); 1490 range.set_start(range.start() - before);
1636 range.set_end(range.end() + after); 1491 range.set_end(range.end() + after);
1637 gfx::Range text_range; 1492 gfx::Range text_range;
1638 if (GetTextRange(&text_range) && text_range.Contains(range)) 1493 if (GetTextRange(&text_range) && text_range.Contains(range))
1639 DeleteRange(range); 1494 DeleteRange(range);
1640 } 1495 }
1641 1496
1642 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {} 1497 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
1643 1498
1644 bool Textfield::IsEditCommandEnabled(int command_id) const { 1499 bool Textfield::IsEditCommandEnabled(int command_id) const {
1645 return IsCommandIdEnabled(command_id); 1500 base::string16 result;
1501 bool editable = !read_only();
1502 bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
1503 switch (command_id) {
1504 case IDS_APP_UNDO:
1505 return editable && model_->CanUndo();
1506 case IDS_APP_REDO:
1507 return editable && model_->CanRedo();
1508 case IDS_APP_CUT:
1509 return editable && readable && model_->HasSelection();
1510 case IDS_APP_COPY:
1511 return readable && model_->HasSelection();
1512 case IDS_APP_PASTE:
1513 ui::Clipboard::GetForCurrentThread()->ReadText(
1514 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1515 return editable && !result.empty();
1516 case IDS_APP_DELETE:
1517 return editable && model_->HasSelection();
1518 case IDS_APP_SELECT_ALL:
1519 return !text().empty();
1520 case IDS_DELETE_FORWARD:
1521 case IDS_DELETE_BACKWARD:
1522 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1523 case IDS_DELETE_TO_END_OF_LINE:
1524 case IDS_DELETE_WORD_BACKWARD:
1525 case IDS_DELETE_WORD_FORWARD:
1526 return editable;
1527 case IDS_MOVE_LEFT:
1528 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1529 case IDS_MOVE_RIGHT:
1530 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1531 case IDS_MOVE_WORD_LEFT:
1532 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1533 case IDS_MOVE_WORD_RIGHT:
1534 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1535 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1536 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1537 case IDS_MOVE_TO_END_OF_LINE:
1538 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1539 return true;
1540 default:
1541 return false;
1542 }
1646 } 1543 }
1647 1544
1648 void Textfield::SetEditCommandForNextKeyEvent(int command_id) { 1545 void Textfield::SetEditCommandForNextKeyEvent(int command_id) {
1649 DCHECK_EQ(kNoCommand, scheduled_edit_command_); 1546 DCHECK_EQ(kNoCommand, scheduled_edit_command_);
1650 scheduled_edit_command_ = command_id; 1547 scheduled_edit_command_ = command_id;
1651 } 1548 }
1652 1549
1653 //////////////////////////////////////////////////////////////////////////////// 1550 ////////////////////////////////////////////////////////////////////////////////
1654 // Textfield, protected: 1551 // Textfield, protected:
1655 1552
(...skipping 14 matching lines...) Expand all
1670 return model_->render_text(); 1567 return model_->render_text();
1671 } 1568 }
1672 1569
1673 base::string16 Textfield::GetSelectionClipboardText() const { 1570 base::string16 Textfield::GetSelectionClipboardText() const {
1674 base::string16 selection_clipboard_text; 1571 base::string16 selection_clipboard_text;
1675 ui::Clipboard::GetForCurrentThread()->ReadText( 1572 ui::Clipboard::GetForCurrentThread()->ReadText(
1676 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); 1573 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
1677 return selection_clipboard_text; 1574 return selection_clipboard_text;
1678 } 1575 }
1679 1576
1577 void Textfield::ExecuteEditCommand(int command_id) {
1578 DestroyTouchSelection();
1579
1580 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent
1581 // modifications of the command should happen here.
1582 if (HasSelection()) {
1583 switch (command_id) {
1584 case IDS_DELETE_WORD_BACKWARD:
1585 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1586 command_id = IDS_DELETE_BACKWARD;
1587 break;
1588 case IDS_DELETE_WORD_FORWARD:
1589 case IDS_DELETE_TO_END_OF_LINE:
1590 command_id = IDS_DELETE_FORWARD;
1591 break;
1592 }
1593 }
1594
1595 // We only execute the commands enabled in Textfield::IsEditCommandEnabled
1596 // below. Hence don't do a virtual IsEditCommandEnabled call.
1597 if (!Textfield::IsEditCommandEnabled(command_id))
1598 return;
1599
1600 bool text_changed = false;
1601 bool cursor_changed = false;
1602 bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
1603 gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
1604 gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
1605 gfx::SelectionModel selection_model = GetSelectionModel();
1606
1607 OnBeforeUserAction();
1608 switch (command_id) {
1609 case IDS_APP_UNDO:
1610 text_changed = cursor_changed = model_->Undo();
1611 break;
1612 case IDS_APP_REDO:
1613 text_changed = cursor_changed = model_->Redo();
1614 break;
1615 case IDS_APP_CUT:
1616 text_changed = cursor_changed = Cut();
1617 break;
1618 case IDS_APP_COPY:
1619 Copy();
1620 break;
1621 case IDS_APP_PASTE:
1622 text_changed = cursor_changed = Paste();
1623 break;
1624 case IDS_APP_DELETE:
1625 text_changed = cursor_changed = model_->Delete();
1626 break;
1627 case IDS_APP_SELECT_ALL:
1628 SelectAll(false);
1629 break;
1630 case IDS_DELETE_BACKWARD:
1631 text_changed = cursor_changed = model_->Backspace();
1632 break;
1633 case IDS_DELETE_FORWARD:
1634 text_changed = cursor_changed = model_->Delete();
1635 break;
1636 case IDS_DELETE_TO_END_OF_LINE:
1637 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1638 text_changed = cursor_changed = model_->Delete();
1639 break;
1640 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1641 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1642 text_changed = cursor_changed = model_->Backspace();
1643 break;
1644 case IDS_DELETE_WORD_BACKWARD:
1645 model_->MoveCursor(gfx::WORD_BREAK, begin, true);
1646 text_changed = cursor_changed = model_->Backspace();
1647 break;
1648 case IDS_DELETE_WORD_FORWARD:
1649 model_->MoveCursor(gfx::WORD_BREAK, end, true);
1650 text_changed = cursor_changed = model_->Delete();
1651 break;
1652 case IDS_MOVE_LEFT:
1653 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
1654 break;
1655 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1656 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
1657 break;
1658 case IDS_MOVE_RIGHT:
1659 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
1660 break;
1661 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1662 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
1663 break;
1664 case IDS_MOVE_WORD_LEFT:
1665 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
1666 break;
1667 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1668 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
1669 break;
1670 case IDS_MOVE_WORD_RIGHT:
1671 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
1672 break;
1673 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1674 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
1675 break;
1676 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1677 model_->MoveCursor(gfx::LINE_BREAK, begin, false);
1678 break;
1679 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1680 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1681 break;
1682 case IDS_MOVE_TO_END_OF_LINE:
1683 model_->MoveCursor(gfx::LINE_BREAK, end, false);
1684 break;
1685 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1686 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1687 break;
1688 default:
1689 NOTREACHED();
1690 break;
1691 }
1692
1693 cursor_changed |= GetSelectionModel() != selection_model;
1694 if (cursor_changed)
1695 UpdateSelectionClipboard();
1696 UpdateAfterChange(text_changed, cursor_changed);
1697 OnAfterUserAction();
1698 }
1699
1680 //////////////////////////////////////////////////////////////////////////////// 1700 ////////////////////////////////////////////////////////////////////////////////
1681 // Textfield, private: 1701 // Textfield, private:
1682 1702
1683 void Textfield::AccessibilitySetValue(const base::string16& new_value) { 1703 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
1684 if (!read_only()) { 1704 if (!read_only()) {
1685 SetText(new_value); 1705 SetText(new_value);
1686 ClearSelection(); 1706 ClearSelection();
1687 } 1707 }
1688 } 1708 }
1689 1709
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1846 context_menu_contents_.reset(new ui::SimpleMenuModel(this)); 1866 context_menu_contents_.reset(new ui::SimpleMenuModel(this));
1847 context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO); 1867 context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
1848 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1868 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1849 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); 1869 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
1850 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); 1870 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
1851 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); 1871 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
1852 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); 1872 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
1853 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1873 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1854 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, 1874 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
1855 IDS_APP_SELECT_ALL); 1875 IDS_APP_SELECT_ALL);
1876
1877 // If the controller adds menu commands, also override ExecuteCommand() and
1878 // IsCommandIdEnabled() as appropriate, for the commands added.
1856 if (controller_) 1879 if (controller_)
1857 controller_->UpdateContextMenu(context_menu_contents_.get()); 1880 controller_->UpdateContextMenu(context_menu_contents_.get());
1858 } 1881 }
1859 context_menu_runner_.reset( 1882 context_menu_runner_.reset(
1860 new MenuRunner(context_menu_contents_.get(), 1883 new MenuRunner(context_menu_contents_.get(),
1861 MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU)); 1884 MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
1862 } 1885 }
1863 1886
1864 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { 1887 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
1865 if (event.IsOnlyLeftMouseButton()) { 1888 if (event.IsOnlyLeftMouseButton()) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 RequestFocus(); 1952 RequestFocus();
1930 model_->MoveCursorTo(mouse); 1953 model_->MoveCursorTo(mouse);
1931 if (!selection_clipboard_text.empty()) { 1954 if (!selection_clipboard_text.empty()) {
1932 model_->InsertText(selection_clipboard_text); 1955 model_->InsertText(selection_clipboard_text);
1933 UpdateAfterChange(true, true); 1956 UpdateAfterChange(true, true);
1934 } 1957 }
1935 OnAfterUserAction(); 1958 OnAfterUserAction();
1936 } 1959 }
1937 1960
1938 } // namespace views 1961 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/textfield/textfield.h ('k') | ui/views/view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698