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

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 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; 186 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
187 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; 187 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
188 case ui::TextEditCommandAuraLinux::MOVE_DOWN: 188 case ui::TextEditCommandAuraLinux::MOVE_DOWN:
189 return IDS_MOVE_DOWN; 189 return IDS_MOVE_DOWN;
190 case ui::TextEditCommandAuraLinux::MOVE_FORWARD: 190 case ui::TextEditCommandAuraLinux::MOVE_FORWARD:
191 if (rtl) 191 if (rtl)
192 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; 192 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
193 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; 193 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
194 case ui::TextEditCommandAuraLinux::MOVE_LEFT: 194 case ui::TextEditCommandAuraLinux::MOVE_LEFT:
195 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT; 195 return select ? IDS_MOVE_LEFT_AND_MODIFY_SELECTION : IDS_MOVE_LEFT;
196 // Todo why are these not mapped-- for omnibox?
tapted 2016/06/08 03:56:45 maybe remove this for now? Otherwise, we should d
karandeepb 2016/06/09 03:37:38 Done.
196 case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN: 197 case ui::TextEditCommandAuraLinux::MOVE_PAGE_DOWN:
197 case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP: 198 case ui::TextEditCommandAuraLinux::MOVE_PAGE_UP:
198 return kNoCommand; 199 return kNoCommand;
199 case ui::TextEditCommandAuraLinux::MOVE_RIGHT: 200 case ui::TextEditCommandAuraLinux::MOVE_RIGHT:
200 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT; 201 return select ? IDS_MOVE_RIGHT_AND_MODIFY_SELECTION : IDS_MOVE_RIGHT;
201 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT: 202 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_DOCUMENT:
202 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE: 203 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_LINE:
203 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH: 204 case ui::TextEditCommandAuraLinux::MOVE_TO_BEGINING_OF_PARAGRAPH:
204 return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION : 205 return select ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
205 IDS_MOVE_TO_BEGINNING_OF_LINE; 206 IDS_MOVE_TO_BEGINNING_OF_LINE;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 } 242 }
242 return kNoCommand; 243 return kNoCommand;
243 } 244 }
244 #endif 245 #endif
245 246
246 const gfx::FontList& GetDefaultFontList() { 247 const gfx::FontList& GetDefaultFontList() {
247 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 248 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
248 return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta); 249 return rb.GetFontListWithDelta(ui::kLabelFontSizeDelta);
249 } 250 }
250 251
252 // Returns true if |command_id| is a menu action installed by this textfield.
253 // Keep in sync with UpdateContextMenu.
254 bool IsMenuCommand(int command_id) {
255 switch (command_id) {
256 case IDS_APP_UNDO:
257 case IDS_APP_CUT:
258 case IDS_APP_COPY:
259 case IDS_APP_PASTE:
260 case IDS_APP_DELETE:
261 case IDS_APP_SELECT_ALL:
262 return true;
263 }
264 return false;
265 }
266
251 } // namespace 267 } // namespace
252 268
253 // static 269 // static
254 const char Textfield::kViewClassName[] = "Textfield"; 270 const char Textfield::kViewClassName[] = "Textfield";
255 const int Textfield::kTextPadding = 3; 271 const int Textfield::kTextPadding = 3;
256 272
257 // static 273 // static
258 size_t Textfield::GetCaretBlinkMs() { 274 size_t Textfield::GetCaretBlinkMs() {
259 static const size_t default_value = 500; 275 static const size_t default_value = 500;
260 #if defined(OS_WIN) 276 #if defined(OS_WIN)
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 } 579 }
564 580
565 void Textfield::ClearEditHistory() { 581 void Textfield::ClearEditHistory() {
566 model_->ClearEditHistory(); 582 model_->ClearEditHistory();
567 } 583 }
568 584
569 void Textfield::SetAccessibleName(const base::string16& name) { 585 void Textfield::SetAccessibleName(const base::string16& name) {
570 accessible_name_ = name; 586 accessible_name_ = name;
571 } 587 }
572 588
573 void Textfield::ExecuteCommand(int command_id) {
574 ExecuteCommand(command_id, ui::EF_NONE);
575 }
576
577 bool Textfield::HasTextBeingDragged() { 589 bool Textfield::HasTextBeingDragged() {
578 return initiating_drag_; 590 return initiating_drag_;
579 } 591 }
580 592
581 //////////////////////////////////////////////////////////////////////////////// 593 ////////////////////////////////////////////////////////////////////////////////
582 // Textfield, View overrides: 594 // Textfield, View overrides:
583 595
584 gfx::Insets Textfield::GetInsets() const { 596 gfx::Insets Textfield::GetInsets() const {
585 gfx::Insets insets = View::GetInsets(); 597 gfx::Insets insets = View::GetInsets();
586 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding); 598 insets += gfx::Insets(kTextPadding, kTextPadding, kTextPadding, kTextPadding);
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 return handled; 722 return handled;
711 723
712 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 724 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
713 ui::TextEditKeyBindingsDelegateAuraLinux* delegate = 725 ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
714 ui::GetTextEditKeyBindingsDelegate(); 726 ui::GetTextEditKeyBindingsDelegate();
715 std::vector<ui::TextEditCommandAuraLinux> commands; 727 std::vector<ui::TextEditCommandAuraLinux> commands;
716 if (!handled && delegate && delegate->MatchEvent(event, &commands)) { 728 if (!handled && delegate && delegate->MatchEvent(event, &commands)) {
717 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; 729 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
718 for (size_t i = 0; i < commands.size(); ++i) { 730 for (size_t i = 0; i < commands.size(); ++i) {
719 const int command = GetViewsCommand(commands[i], rtl); 731 const int command = GetViewsCommand(commands[i], rtl);
720 if (IsCommandIdEnabled(command)) { 732 if (IsEditCommandEnabled(command)) {
721 ExecuteCommand(command); 733 ExecuteEditCommand(command);
722 handled = true; 734 handled = true;
723 } 735 }
724 } 736 }
725 return handled; 737 return handled;
726 } 738 }
727 #endif 739 #endif
728 740
729 if (edit_command == kNoCommand) 741 if (edit_command == kNoCommand)
730 edit_command = GetCommandForKeyEvent(event); 742 edit_command = GetCommandForKeyEvent(event);
731 743
732 if (!handled && IsCommandIdEnabled(edit_command)) { 744 if (!handled && IsEditCommandEnabled(edit_command)) {
733 ExecuteCommand(edit_command); 745 ExecuteEditCommand(edit_command);
734 handled = true; 746 handled = true;
735 } 747 }
736 return handled; 748 return handled;
737 } 749 }
738 750
739 void Textfield::OnGestureEvent(ui::GestureEvent* event) { 751 void Textfield::OnGestureEvent(ui::GestureEvent* event) {
740 switch (event->type()) { 752 switch (event->type()) {
741 case ui::ET_GESTURE_TAP_DOWN: 753 case ui::ET_GESTURE_TAP_DOWN:
742 RequestFocus(); 754 RequestFocus();
743 ShowImeIfNeeded(); 755 ShowImeIfNeeded();
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 break; 839 break;
828 default: 840 default:
829 return; 841 return;
830 } 842 }
831 } 843 }
832 844
833 // This function is called by BrowserView to execute clipboard commands. 845 // This function is called by BrowserView to execute clipboard commands.
834 bool Textfield::AcceleratorPressed(const ui::Accelerator& accelerator) { 846 bool Textfield::AcceleratorPressed(const ui::Accelerator& accelerator) {
835 ui::KeyEvent event(accelerator.type(), accelerator.key_code(), 847 ui::KeyEvent event(accelerator.type(), accelerator.key_code(),
836 accelerator.modifiers()); 848 accelerator.modifiers());
837 ExecuteCommand(GetCommandForKeyEvent(event)); 849 ExecuteEditCommand(GetCommandForKeyEvent(event));
838 return true; 850 return true;
839 } 851 }
840 852
841 bool Textfield::CanHandleAccelerators() const { 853 bool Textfield::CanHandleAccelerators() const {
842 return GetRenderText()->focused() && View::CanHandleAccelerators(); 854 return GetRenderText()->focused() && View::CanHandleAccelerators();
843 } 855 }
844 856
845 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) { 857 void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
846 SelectAll(false); 858 SelectAll(false);
847 } 859 }
848 860
849 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) { 861 bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
850 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) 862 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
851 // Skip any accelerator handling that conflicts with custom keybindings. 863 // Skip any accelerator handling that conflicts with custom keybindings.
852 ui::TextEditKeyBindingsDelegateAuraLinux* delegate = 864 ui::TextEditKeyBindingsDelegateAuraLinux* delegate =
853 ui::GetTextEditKeyBindingsDelegate(); 865 ui::GetTextEditKeyBindingsDelegate();
854 std::vector<ui::TextEditCommandAuraLinux> commands; 866 std::vector<ui::TextEditCommandAuraLinux> commands;
855 if (delegate && delegate->MatchEvent(event, &commands)) { 867 if (delegate && delegate->MatchEvent(event, &commands)) {
856 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT; 868 const bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
857 for (size_t i = 0; i < commands.size(); ++i) 869 for (size_t i = 0; i < commands.size(); ++i)
858 if (IsCommandIdEnabled(GetViewsCommand(commands[i], rtl))) 870 if (IsEditCommandEnabled(GetViewsCommand(commands[i], rtl)))
859 return true; 871 return true;
860 } 872 }
861 #endif 873 #endif
862 874
863 // Skip backspace accelerator handling; editable textfields handle this key. 875 // Skip backspace accelerator handling; editable textfields handle this key.
864 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes. 876 // Also skip processing Windows [Alt]+<num-pad digit> Unicode alt-codes.
865 const bool is_backspace = event.key_code() == ui::VKEY_BACK; 877 const bool is_backspace = event.key_code() == ui::VKEY_BACK;
866 return (is_backspace && !read_only()) || event.IsUnicodeKeyCode(); 878 return (is_backspace && !read_only()) || event.IsUnicodeKeyCode();
867 } 879 }
868 880
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 } 1233 }
1222 1234
1223 //////////////////////////////////////////////////////////////////////////////// 1235 ////////////////////////////////////////////////////////////////////////////////
1224 // Textfield, ui::SimpleMenuModel::Delegate overrides: 1236 // Textfield, ui::SimpleMenuModel::Delegate overrides:
1225 1237
1226 bool Textfield::IsCommandIdChecked(int command_id) const { 1238 bool Textfield::IsCommandIdChecked(int command_id) const {
1227 return true; 1239 return true;
1228 } 1240 }
1229 1241
1230 bool Textfield::IsCommandIdEnabled(int command_id) const { 1242 bool Textfield::IsCommandIdEnabled(int command_id) const {
1231 base::string16 result; 1243 return IsMenuCommand(command_id) &&
tapted 2016/06/08 03:56:45 So.. I'm not sure whether `IsMenuCommand() adds mu
karandeepb 2016/06/09 03:37:38 Have added a comment in UpdateContextMenu.
1232 bool editable = !read_only(); 1244 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 } 1245 }
1275 1246
1276 bool Textfield::GetAcceleratorForCommandId(int command_id, 1247 bool Textfield::GetAcceleratorForCommandId(int command_id,
1277 ui::Accelerator* accelerator) { 1248 ui::Accelerator* accelerator) {
1278 switch (command_id) { 1249 switch (command_id) {
1279 case IDS_APP_UNDO: 1250 case IDS_APP_UNDO:
1280 *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN); 1251 *accelerator = ui::Accelerator(ui::VKEY_Z, ui::EF_CONTROL_DOWN);
1281 return true; 1252 return true;
1282 1253
1283 case IDS_APP_CUT: 1254 case IDS_APP_CUT:
(...skipping 13 matching lines...) Expand all
1297 return true; 1268 return true;
1298 1269
1299 default: 1270 default:
1300 return false; 1271 return false;
1301 } 1272 }
1302 } 1273 }
1303 1274
1304 void Textfield::ExecuteCommand(int command_id, int event_flags) { 1275 void Textfield::ExecuteCommand(int command_id, int event_flags) {
1305 if (!Textfield::IsCommandIdEnabled(command_id)) 1276 if (!Textfield::IsCommandIdEnabled(command_id))
1306 return; 1277 return;
1307 1278 Textfield::ExecuteEditCommand(command_id);
tapted 2016/06/08 03:56:45 Something like // Items selected from the context
karandeepb 2016/06/09 03:37:38 Have added a comment in UpdateContextMenu.
1308 DestroyTouchSelection();
1309
1310 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent
1311 // modifications of the command should happen here.
1312 if (HasSelection()) {
1313 switch (command_id) {
1314 case IDS_DELETE_WORD_BACKWARD:
1315 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1316 command_id = IDS_DELETE_BACKWARD;
1317 break;
1318 case IDS_DELETE_WORD_FORWARD:
1319 case IDS_DELETE_TO_END_OF_LINE:
1320 command_id = IDS_DELETE_FORWARD;
1321 break;
1322 }
1323 }
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 } 1279 }
1424 1280
1425 //////////////////////////////////////////////////////////////////////////////// 1281 ////////////////////////////////////////////////////////////////////////////////
1426 // Textfield, ui::TextInputClient overrides: 1282 // Textfield, ui::TextInputClient overrides:
1427 1283
1428 void Textfield::SetCompositionText(const ui::CompositionText& composition) { 1284 void Textfield::SetCompositionText(const ui::CompositionText& composition) {
1429 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) 1285 if (GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
1430 return; 1286 return;
1431 1287
1432 OnBeforeUserAction(); 1288 OnBeforeUserAction();
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
1635 range.set_start(range.start() - before); 1491 range.set_start(range.start() - before);
1636 range.set_end(range.end() + after); 1492 range.set_end(range.end() + after);
1637 gfx::Range text_range; 1493 gfx::Range text_range;
1638 if (GetTextRange(&text_range) && text_range.Contains(range)) 1494 if (GetTextRange(&text_range) && text_range.Contains(range))
1639 DeleteRange(range); 1495 DeleteRange(range);
1640 } 1496 }
1641 1497
1642 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {} 1498 void Textfield::EnsureCaretInRect(const gfx::Rect& rect) {}
1643 1499
1644 bool Textfield::IsEditCommandEnabled(int command_id) const { 1500 bool Textfield::IsEditCommandEnabled(int command_id) const {
1645 return IsCommandIdEnabled(command_id); 1501 base::string16 result;
1502 bool editable = !read_only();
1503 bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
1504 switch (command_id) {
1505 case IDS_APP_UNDO:
1506 return editable && model_->CanUndo();
1507 case IDS_APP_REDO:
1508 return editable && model_->CanRedo();
1509 case IDS_APP_CUT:
1510 return editable && readable && model_->HasSelection();
1511 case IDS_APP_COPY:
1512 return readable && model_->HasSelection();
1513 case IDS_APP_PASTE:
1514 ui::Clipboard::GetForCurrentThread()->ReadText(
1515 ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
1516 return editable && !result.empty();
1517 case IDS_APP_DELETE:
1518 return editable && model_->HasSelection();
1519 case IDS_APP_SELECT_ALL:
1520 return !text().empty();
1521 case IDS_DELETE_FORWARD:
1522 case IDS_DELETE_BACKWARD:
1523 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1524 case IDS_DELETE_TO_END_OF_LINE:
1525 case IDS_DELETE_WORD_BACKWARD:
1526 case IDS_DELETE_WORD_FORWARD:
1527 return editable;
1528 case IDS_MOVE_LEFT:
1529 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1530 case IDS_MOVE_RIGHT:
1531 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1532 case IDS_MOVE_WORD_LEFT:
1533 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1534 case IDS_MOVE_WORD_RIGHT:
1535 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1536 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1537 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1538 case IDS_MOVE_TO_END_OF_LINE:
1539 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1540 return true;
1541 default:
1542 return false;
1543 }
1646 } 1544 }
1647 1545
1648 void Textfield::SetEditCommandForNextKeyEvent(int command_id) { 1546 void Textfield::SetEditCommandForNextKeyEvent(int command_id) {
1649 DCHECK_EQ(kNoCommand, scheduled_edit_command_); 1547 DCHECK_EQ(kNoCommand, scheduled_edit_command_);
1650 scheduled_edit_command_ = command_id; 1548 scheduled_edit_command_ = command_id;
1651 } 1549 }
1652 1550
1653 //////////////////////////////////////////////////////////////////////////////// 1551 ////////////////////////////////////////////////////////////////////////////////
1654 // Textfield, protected: 1552 // Textfield, protected:
1655 1553
(...skipping 14 matching lines...) Expand all
1670 return model_->render_text(); 1568 return model_->render_text();
1671 } 1569 }
1672 1570
1673 base::string16 Textfield::GetSelectionClipboardText() const { 1571 base::string16 Textfield::GetSelectionClipboardText() const {
1674 base::string16 selection_clipboard_text; 1572 base::string16 selection_clipboard_text;
1675 ui::Clipboard::GetForCurrentThread()->ReadText( 1573 ui::Clipboard::GetForCurrentThread()->ReadText(
1676 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text); 1574 ui::CLIPBOARD_TYPE_SELECTION, &selection_clipboard_text);
1677 return selection_clipboard_text; 1575 return selection_clipboard_text;
1678 } 1576 }
1679 1577
1578 void Textfield::ExecuteEditCommand(int command_id) {
1579 if (!Textfield::IsEditCommandEnabled(command_id))
1580 return;
1581
1582 DestroyTouchSelection();
1583
1584 // Some codepaths may bypass GetCommandForKeyEvent, so any selection-dependent
1585 // modifications of the command should happen here.
1586 if (HasSelection()) {
1587 switch (command_id) {
1588 case IDS_DELETE_WORD_BACKWARD:
1589 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1590 command_id = IDS_DELETE_BACKWARD;
1591 break;
1592 case IDS_DELETE_WORD_FORWARD:
1593 case IDS_DELETE_TO_END_OF_LINE:
1594 command_id = IDS_DELETE_FORWARD;
1595 break;
1596 }
1597 }
1598
1599 bool text_changed = false;
1600 bool cursor_changed = false;
1601 bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
1602 gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
1603 gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
1604 gfx::SelectionModel selection_model = GetSelectionModel();
1605
1606 OnBeforeUserAction();
1607 switch (command_id) {
1608 case IDS_APP_UNDO:
1609 text_changed = cursor_changed = model_->Undo();
1610 break;
1611 case IDS_APP_REDO:
1612 text_changed = cursor_changed = model_->Redo();
1613 break;
1614 case IDS_APP_CUT:
1615 text_changed = cursor_changed = Cut();
1616 break;
1617 case IDS_APP_COPY:
1618 Copy();
1619 break;
1620 case IDS_APP_PASTE:
1621 text_changed = cursor_changed = Paste();
1622 break;
1623 case IDS_APP_DELETE:
1624 text_changed = cursor_changed = model_->Delete();
1625 break;
1626 case IDS_APP_SELECT_ALL:
1627 SelectAll(false);
1628 break;
1629 case IDS_DELETE_BACKWARD:
1630 text_changed = cursor_changed = model_->Backspace();
1631 break;
1632 case IDS_DELETE_FORWARD:
1633 text_changed = cursor_changed = model_->Delete();
1634 break;
1635 case IDS_DELETE_TO_END_OF_LINE:
1636 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1637 text_changed = cursor_changed = model_->Delete();
1638 break;
1639 case IDS_DELETE_TO_BEGINNING_OF_LINE:
1640 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1641 text_changed = cursor_changed = model_->Backspace();
1642 break;
1643 case IDS_DELETE_WORD_BACKWARD:
1644 model_->MoveCursor(gfx::WORD_BREAK, begin, true);
1645 text_changed = cursor_changed = model_->Backspace();
1646 break;
1647 case IDS_DELETE_WORD_FORWARD:
1648 model_->MoveCursor(gfx::WORD_BREAK, end, true);
1649 text_changed = cursor_changed = model_->Delete();
1650 break;
1651 case IDS_MOVE_LEFT:
1652 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
1653 break;
1654 case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
1655 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
1656 break;
1657 case IDS_MOVE_RIGHT:
1658 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
1659 break;
1660 case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
1661 model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
1662 break;
1663 case IDS_MOVE_WORD_LEFT:
1664 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
1665 break;
1666 case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
1667 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
1668 break;
1669 case IDS_MOVE_WORD_RIGHT:
1670 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
1671 break;
1672 case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
1673 model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
1674 break;
1675 case IDS_MOVE_TO_BEGINNING_OF_LINE:
1676 model_->MoveCursor(gfx::LINE_BREAK, begin, false);
1677 break;
1678 case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
1679 model_->MoveCursor(gfx::LINE_BREAK, begin, true);
1680 break;
1681 case IDS_MOVE_TO_END_OF_LINE:
1682 model_->MoveCursor(gfx::LINE_BREAK, end, false);
1683 break;
1684 case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
1685 model_->MoveCursor(gfx::LINE_BREAK, end, true);
1686 break;
1687 default:
1688 NOTREACHED();
1689 break;
1690 }
1691
1692 cursor_changed |= GetSelectionModel() != selection_model;
1693 if (cursor_changed)
1694 UpdateSelectionClipboard();
1695 UpdateAfterChange(text_changed, cursor_changed);
1696 OnAfterUserAction();
1697 }
1698
1680 //////////////////////////////////////////////////////////////////////////////// 1699 ////////////////////////////////////////////////////////////////////////////////
1681 // Textfield, private: 1700 // Textfield, private:
1682 1701
1683 void Textfield::AccessibilitySetValue(const base::string16& new_value) { 1702 void Textfield::AccessibilitySetValue(const base::string16& new_value) {
1684 if (!read_only()) { 1703 if (!read_only()) {
1685 SetText(new_value); 1704 SetText(new_value);
1686 ClearSelection(); 1705 ClearSelection();
1687 } 1706 }
1688 } 1707 }
1689 1708
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1929 RequestFocus(); 1948 RequestFocus();
1930 model_->MoveCursorTo(mouse); 1949 model_->MoveCursorTo(mouse);
1931 if (!selection_clipboard_text.empty()) { 1950 if (!selection_clipboard_text.empty()) {
1932 model_->InsertText(selection_clipboard_text); 1951 model_->InsertText(selection_clipboard_text);
1933 UpdateAfterChange(true, true); 1952 UpdateAfterChange(true, true);
1934 } 1953 }
1935 OnAfterUserAction(); 1954 OnAfterUserAction();
1936 } 1955 }
1937 1956
1938 } // namespace views 1957 } // 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