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

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) &&
tapted 2016/06/09 04:10:03 I'm still dubious about the merit of the `IsMenuCo
karandeepb 2016/06/09 04:51:42 IsMenuCommand is replaced by ui::TextEditCommand G
tapted 2016/06/09 05:02:01 Gotcha - it makes a lot more sense with that conte
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 11 matching lines...) Expand all
1295 case IDS_APP_SELECT_ALL: 1265 case IDS_APP_SELECT_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 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent
1306 // modifications of the command should happen here.
1307 if (HasSelection()) {
1308 switch (command_id) {
1309 case IDS_DELETE_WORD_BACKWARD:
1310 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1311 command_id = IDS_DELETE_BACKWARD;
1312 break;
1313 case IDS_DELETE_WORD_FORWARD:
1314 case IDS_DELETE_TO_END_OF_LINE:
1315 command_id = IDS_DELETE_FORWARD;
1316 break;
1317 }
1318 }
1319
1320 // We only execute the commands enabled in Textfield::IsCommandIdEnabled
1321 // below. Hence don't do a virtual IsCommandIdEnabled call.
1322 if (!Textfield::IsCommandIdEnabled(command_id)) 1275 if (!Textfield::IsCommandIdEnabled(command_id))
1323 return; 1276 return;
1324 1277 Textfield::ExecuteEditCommand(command_id);
1325 DestroyTouchSelection();
1326
1327 bool text_changed = false;
1328 bool cursor_changed = false;
1329 bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
1330 gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
1331 gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
1332 gfx::SelectionModel selection_model = GetSelectionModel();
1333
1334 OnBeforeUserAction();
1335 switch (command_id) {
1336 case IDS_APP_UNDO:
1337 text_changed = cursor_changed = model_->Undo();
1338 break;
1339 case IDS_APP_REDO:
1340 text_changed = cursor_changed = model_->Redo();
1341 break;
1342 case IDS_APP_CUT:
1343 text_changed = cursor_changed = Cut();
1344 break;
1345 case IDS_APP_COPY:
1346 Copy();
1347 break;
1348 case IDS_APP_PASTE:
1349 text_changed = cursor_changed = Paste();
1350 break;
1351 case IDS_APP_DELETE:
1352 text_changed = cursor_changed = model_->Delete();
1353 break;
1354 case IDS_APP_SELECT_ALL:
1355 SelectAll(false);
1356 break;
1357 case IDS_DELETE_BACKWARD:
1358 text_changed = cursor_changed = model_->Backspace();
1359 break;
1360 case IDS_DELETE_FORWARD:
1361 text_changed = cursor_changed = model_->Delete();
1362 break;
1363 case IDS_DELETE_TO_END_OF_LINE:
1364 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1365 text_changed = cursor_changed = model_->Delete();
1366 break;
1367 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1368 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1369 text_changed = cursor_changed = model_->Backspace();
1370 break;
1371 case IDS_DELETE_WORD_BACKWARD:
1372 model_->MoveCursor(gfx::WORD_BREAK, begin, true);
1373 text_changed = cursor_changed = model_->Backspace();
1374 break;
1375 case IDS_DELETE_WORD_FORWARD:
1376 model_->MoveCursor(gfx::WORD_BREAK, end, true);
1377 text_changed = cursor_changed = model_->Delete();
1378 break;
1379 case IDS_MOVE_LEFT:
1380 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
1381 break;
1382 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1383 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
1384 break;
1385 case IDS_MOVE_RIGHT:
1386 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
1387 break;
1388 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1389 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
1390 break;
1391 case IDS_MOVE_WORD_LEFT:
1392 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
1393 break;
1394 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1395 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
1396 break;
1397 case IDS_MOVE_WORD_RIGHT:
1398 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
1399 break;
1400 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1401 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
1402 break;
1403 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1404 model_->MoveCursor(gfx::LINE_BREAK, begin, false);
1405 break;
1406 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1407 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1408 break;
1409 case IDS_MOVE_TO_END_OF_LINE:
1410 model_->MoveCursor(gfx::LINE_BREAK, end, false);
1411 break;
1412 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1413 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1414 break;
1415 default:
1416 NOTREACHED();
1417 break;
1418 }
1419
1420 cursor_changed |= GetSelectionModel() != selection_model;
1421 if (cursor_changed)
1422 UpdateSelectionClipboard();
1423 UpdateAfterChange(text_changed, cursor_changed);
1424 OnAfterUserAction();
1425 } 1278 }
1426 1279
1427 //////////////////////////////////////////////////////////////////////////////// 1280 ////////////////////////////////////////////////////////////////////////////////
1428 // Textfield, ui::TextInputClient overrides: 1281 // Textfield, ui::TextInputClient overrides:
1429 1282
1430 void Textfield::SetCompositionText(const ui::CompositionText& composition) { 1283 void Textfield::SetCompositionText(const ui::CompositionText& composition) {
1431 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1284 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1432 return; 1285 return;
1433 1286
1434 OnBeforeUserAction(); 1287 OnBeforeUserAction();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1637 range.set_start(range.start() - before); 1490 range.set_start(range.start() - before);
1638 range.set_end(range.end() + after); 1491 range.set_end(range.end() + after);
1639 gfx::Range text_range; 1492 gfx::Range text_range;
1640 if (GetTextRange(&text_range) && text_range.Contains(range)) 1493 if (GetTextRange(&text_range) && text_range.Contains(range))
1641 DeleteRange(range); 1494 DeleteRange(range);
1642 } 1495 }
1643 1496
1644 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {} 1497 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
1645 1498
1646 bool Textfield::IsEditCommandEnabled(int command_id) const { 1499 bool Textfield::IsEditCommandEnabled(int command_id) const {
1647 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 }
1648 } 1543 }
1649 1544
1650 void Textfield::SetEditCommandForNextKeyEvent(int command_id) { 1545 void Textfield::SetEditCommandForNextKeyEvent(int command_id) {
1651 DCHECK_EQ(kNoCommand, scheduled_edit_command_); 1546 DCHECK_EQ(kNoCommand, scheduled_edit_command_);
1652 scheduled_edit_command_ = command_id; 1547 scheduled_edit_command_ = command_id;
1653 } 1548 }
1654 1549
1655 //////////////////////////////////////////////////////////////////////////////// 1550 ////////////////////////////////////////////////////////////////////////////////
1656 // Textfield, protected: 1551 // Textfield, protected:
1657 1552
(...skipping 14 matching lines...) Expand all
1672 return model_->render_text(); 1567 return model_->render_text();
1673 } 1568 }
1674 1569
1675 base::string16 Textfield::GetSelectionClipboardText() const { 1570 base::string16 Textfield::GetSelectionClipboardText() const {
1676 base::string16 selection_clipboard_text; 1571 base::string16 selection_clipboard_text;
1677 ui::Clipboard::GetForCurrentThread()->ReadText( 1572 ui::Clipboard::GetForCurrentThread()->ReadText(
1678 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); 1573 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
1679 return selection_clipboard_text; 1574 return selection_clipboard_text;
1680 } 1575 }
1681 1576
1577 void Textfield::ExecuteEditCommand(int command_id) {
1578 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent
1579 // modifications of the command should happen here.
1580 if (HasSelection()) {
1581 switch (command_id) {
1582 case IDS_DELETE_WORD_BACKWARD:
1583 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1584 command_id = IDS_DELETE_BACKWARD;
1585 break;
1586 case IDS_DELETE_WORD_FORWARD:
1587 case IDS_DELETE_TO_END_OF_LINE:
1588 command_id = IDS_DELETE_FORWARD;
1589 break;
1590 }
1591 }
1592
1593 // We only execute the commands enabled in Textfield::IsEditCommandEnabled
1594 // below. Hence don't do a virtual IsEditCommandEnabled call.
1595 if (!Textfield::IsEditCommandEnabled(command_id))
1596 return;
1597
1598 DestroyTouchSelection();
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
1682 //////////////////////////////////////////////////////////////////////////////// 1700 ////////////////////////////////////////////////////////////////////////////////
1683 // Textfield, private: 1701 // Textfield, private:
1684 1702
1685 void Textfield::AccessibilitySetValue(const base::string16& new_value) { 1703 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
1686 if (!read_only()) { 1704 if (!read_only()) {
1687 SetText(new_value); 1705 SetText(new_value);
1688 ClearSelection(); 1706 ClearSelection();
1689 } 1707 }
1690 } 1708 }
1691 1709
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 context_menu_contents_.reset(new ui::SimpleMenuModel(this)); 1866 context_menu_contents_.reset(new ui::SimpleMenuModel(this));
1849 context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO); 1867 context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
1850 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1868 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1851 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT); 1869 context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
1852 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY); 1870 context_menu_contents_->AddItemWithStringId(IDS_APP_COPY, IDS_APP_COPY);
1853 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE); 1871 context_menu_contents_->AddItemWithStringId(IDS_APP_PASTE, IDS_APP_PASTE);
1854 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE); 1872 context_menu_contents_->AddItemWithStringId(IDS_APP_DELETE, IDS_APP_DELETE);
1855 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR); 1873 context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
1856 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL, 1874 context_menu_contents_->AddItemWithStringId(IDS_APP_SELECT_ALL,
1857 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.
tapted 2016/06/09 04:10:03 I don't think it makes sense for UpdateContextMenu
karandeepb 2016/06/09 04:51:43 Yeah, I agree. Will wait for owner's review on thi
1858 if (controller_) 1879 if (controller_)
1859 controller_->UpdateContextMenu(context_menu_contents_.get()); 1880 controller_->UpdateContextMenu(context_menu_contents_.get());
1860 } 1881 }
1861 context_menu_runner_.reset( 1882 context_menu_runner_.reset(
1862 new MenuRunner(context_menu_contents_.get(), 1883 new MenuRunner(context_menu_contents_.get(),
1863 MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU)); 1884 MenuRunner::HAS_MNEMONICS | MenuRunner::CONTEXT_MENU));
1864 } 1885 }
1865 1886
1866 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) { 1887 void Textfield::TrackMouseClicks(const ui::MouseEvent& event) {
1867 if (event.IsOnlyLeftMouseButton()) { 1888 if (event.IsOnlyLeftMouseButton()) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1931 RequestFocus(); 1952 RequestFocus();
1932 model_->MoveCursorTo(mouse); 1953 model_->MoveCursorTo(mouse);
1933 if (!selection_clipboard_text.empty()) { 1954 if (!selection_clipboard_text.empty()) {
1934 model_->InsertText(selection_clipboard_text); 1955 model_->InsertText(selection_clipboard_text);
1935 UpdateAfterChange(true, true); 1956 UpdateAfterChange(true, true);
1936 } 1957 }
1937 OnAfterUserAction(); 1958 OnAfterUserAction();
1938 } 1959 }
1939 1960
1940 } // 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