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

Side by Side Diff: ui/views/cocoa/bridged_content_view.mm

Issue 2422993002: views::Label: Implement context menu, keyboard shortcuts for copy/select all. (Closed)
Patch Set: Address comments by Trent. Created 4 years, 1 month 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 | « no previous file | ui/views/controls/label.h » ('j') | ui/views/controls/label_unittest.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 #import "ui/views/cocoa/bridged_content_view.h" 5 #import "ui/views/cocoa/bridged_content_view.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/mac/mac_util.h" 8 #import "base/mac/mac_util.h"
9 #import "base/mac/scoped_nsobject.h" 9 #import "base/mac/scoped_nsobject.h"
10 #import "base/mac/sdk_forward_declarations.h" 10 #import "base/mac/sdk_forward_declarations.h"
(...skipping 10 matching lines...) Expand all
21 #include "ui/events/event_utils.h" 21 #include "ui/events/event_utils.h"
22 #include "ui/events/keycodes/dom/dom_code.h" 22 #include "ui/events/keycodes/dom/dom_code.h"
23 #import "ui/events/keycodes/keyboard_code_conversion_mac.h" 23 #import "ui/events/keycodes/keyboard_code_conversion_mac.h"
24 #include "ui/gfx/canvas_paint_mac.h" 24 #include "ui/gfx/canvas_paint_mac.h"
25 #include "ui/gfx/decorated_text.h" 25 #include "ui/gfx/decorated_text.h"
26 #include "ui/gfx/geometry/rect.h" 26 #include "ui/gfx/geometry/rect.h"
27 #import "ui/gfx/mac/coordinate_conversion.h" 27 #import "ui/gfx/mac/coordinate_conversion.h"
28 #include "ui/gfx/path.h" 28 #include "ui/gfx/path.h"
29 #import "ui/gfx/path_mac.h" 29 #import "ui/gfx/path_mac.h"
30 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" 30 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
31 #include "ui/strings/grit/ui_strings.h"
31 #import "ui/views/cocoa/bridged_native_widget.h" 32 #import "ui/views/cocoa/bridged_native_widget.h"
32 #import "ui/views/cocoa/drag_drop_client_mac.h" 33 #import "ui/views/cocoa/drag_drop_client_mac.h"
34 #include "ui/views/controls/label.h"
33 #include "ui/views/controls/menu/menu_config.h" 35 #include "ui/views/controls/menu/menu_config.h"
34 #include "ui/views/controls/menu/menu_controller.h" 36 #include "ui/views/controls/menu/menu_controller.h"
35 #include "ui/views/view.h" 37 #include "ui/views/view.h"
36 #include "ui/views/widget/native_widget_mac.h" 38 #include "ui/views/widget/native_widget_mac.h"
37 #include "ui/views/widget/widget.h" 39 #include "ui/views/widget/widget.h"
38 #include "ui/views/word_lookup_client.h" 40 #include "ui/views/word_lookup_client.h"
39 41
40 using views::MenuController; 42 using views::MenuController;
41 43
42 namespace { 44 namespace {
43 45
46 const int kInvalidTextMenuCommand = 0;
tapted 2016/11/16 08:39:07 0 is valid according to SimpleMenuModel::ValidateI
karandeepb 2016/11/16 23:47:13 Removed GetContextMenuCommandForMenuAction.
47
44 NSString* const kFullKeyboardAccessChangedNotification = 48 NSString* const kFullKeyboardAccessChangedNotification =
45 @"com.apple.KeyboardUIModeDidChange"; 49 @"com.apple.KeyboardUIModeDidChange";
46 50
47 // Returns true if all four corners of |rect| are contained inside |path|. 51 // Returns true if all four corners of |rect| are contained inside |path|.
48 bool IsRectInsidePath(NSRect rect, NSBezierPath* path) { 52 bool IsRectInsidePath(NSRect rect, NSBezierPath* path) {
49 return [path containsPoint:rect.origin] && 53 return [path containsPoint:rect.origin] &&
50 [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width, 54 [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width,
51 rect.origin.y)] && 55 rect.origin.y)] &&
52 [path containsPoint:NSMakePoint(rect.origin.x, 56 [path containsPoint:NSMakePoint(rect.origin.x,
53 rect.origin.y + rect.size.height)] && 57 rect.origin.y + rect.size.height)] &&
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 if (attribute.strike) 244 if (attribute.strike)
241 attrs[NSStrikethroughStyleAttributeName] = line_style; 245 attrs[NSStrikethroughStyleAttributeName] = line_style;
242 246
243 [str setAttributes:attrs range:range]; 247 [str setAttributes:attrs range:range];
244 } 248 }
245 249
246 [str endEditing]; 250 [str endEditing];
247 return str.autorelease(); 251 return str.autorelease();
248 } 252 }
249 253
254 ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
255 if (action == @selector(undo:))
256 return ui::TextEditCommand::UNDO;
257 if (action == @selector(redo:))
258 return ui::TextEditCommand::REDO;
259 if (action == @selector(cut:))
260 return ui::TextEditCommand::CUT;
261 if (action == @selector(copy:))
262 return ui::TextEditCommand::COPY;
263 if (action == @selector(paste:))
264 return ui::TextEditCommand::PASTE;
265 if (action == @selector(selectAll:))
266 return ui::TextEditCommand::SELECT_ALL;
267 return ui::TextEditCommand::INVALID_COMMAND;
268 }
269
270 int GetContextMenuCommandForMenuAction(SEL action) {
271 if (action == @selector(undo:))
272 return IDS_APP_UNDO;
tapted 2016/11/16 08:39:07 I don't really like seeing IDS_ translated string
karandeepb 2016/11/16 23:47:13 Removed this.
273 if (action == @selector(cut:))
274 return IDS_APP_CUT;
275 if (action == @selector(copy:))
276 return IDS_APP_COPY;
277 if (action == @selector(paste:))
278 return IDS_APP_PASTE;
279 if (action == @selector(selectAll:))
280 return IDS_APP_SELECT_ALL;
281 return kInvalidTextMenuCommand;
282 }
283
250 } // namespace 284 } // namespace
251 285
252 @interface BridgedContentView () 286 @interface BridgedContentView ()
253 287
254 // Returns the active menu controller corresponding to |hostedView_|, 288 // Returns the active menu controller corresponding to |hostedView_|,
255 // nil otherwise. 289 // nil otherwise.
256 - (MenuController*)activeMenuController; 290 - (MenuController*)activeMenuController;
257 291
258 // Passes |event| to the InputMethod for dispatch. 292 // Passes |event| to the InputMethod for dispatch.
259 - (void)handleKeyEvent:(ui::KeyEvent*)event; 293 - (void)handleKeyEvent:(ui::KeyEvent*)event;
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
513 } 547 }
514 } 548 }
515 549
516 - (views::DragDropClientMac*)dragDropClient { 550 - (views::DragDropClientMac*)dragDropClient {
517 views::BridgedNativeWidget* bridge = 551 views::BridgedNativeWidget* bridge =
518 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]); 552 views::NativeWidgetMac::GetBridgeForNativeWindow([self window]);
519 return bridge ? bridge->drag_drop_client() : nullptr; 553 return bridge ? bridge->drag_drop_client() : nullptr;
520 } 554 }
521 555
522 - (void)undo:(id)sender { 556 - (void)undo:(id)sender {
523 // This DCHECK is more strict than a similar check in handleAction:. It can be
524 // done here because the actors sending these actions should be calling
525 // validateUserInterfaceItem: before enabling UI that allows these messages to
526 // be sent. Checking it here would be too late to provide correct UI feedback
527 // (e.g. there will be no "beep").
528 DCHECK(textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::UNDO));
529 [self handleAction:ui::TextEditCommand::UNDO 557 [self handleAction:ui::TextEditCommand::UNDO
530 keyCode:ui::VKEY_Z 558 keyCode:ui::VKEY_Z
531 domCode:ui::DomCode::US_Z 559 domCode:ui::DomCode::US_Z
532 eventFlags:ui::EF_CONTROL_DOWN]; 560 eventFlags:ui::EF_CONTROL_DOWN];
533 } 561 }
534 562
535 - (void)redo:(id)sender { 563 - (void)redo:(id)sender {
536 DCHECK(textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::REDO));
537 [self handleAction:ui::TextEditCommand::REDO 564 [self handleAction:ui::TextEditCommand::REDO
538 keyCode:ui::VKEY_Z 565 keyCode:ui::VKEY_Z
539 domCode:ui::DomCode::US_Z 566 domCode:ui::DomCode::US_Z
540 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN]; 567 eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
541 } 568 }
542 569
543 - (void)cut:(id)sender { 570 - (void)cut:(id)sender {
544 DCHECK(textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::CUT));
545 [self handleAction:ui::TextEditCommand::CUT 571 [self handleAction:ui::TextEditCommand::CUT
546 keyCode:ui::VKEY_X 572 keyCode:ui::VKEY_X
547 domCode:ui::DomCode::US_X 573 domCode:ui::DomCode::US_X
548 eventFlags:ui::EF_CONTROL_DOWN]; 574 eventFlags:ui::EF_CONTROL_DOWN];
549 } 575 }
550 576
551 - (void)copy:(id)sender { 577 - (void)copy:(id)sender {
552 DCHECK(textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::COPY));
553 [self handleAction:ui::TextEditCommand::COPY 578 [self handleAction:ui::TextEditCommand::COPY
554 keyCode:ui::VKEY_C 579 keyCode:ui::VKEY_C
555 domCode:ui::DomCode::US_C 580 domCode:ui::DomCode::US_C
556 eventFlags:ui::EF_CONTROL_DOWN]; 581 eventFlags:ui::EF_CONTROL_DOWN];
557 } 582 }
558 583
559 - (void)paste:(id)sender { 584 - (void)paste:(id)sender {
560 DCHECK(
561 textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::PASTE));
562 [self handleAction:ui::TextEditCommand::PASTE 585 [self handleAction:ui::TextEditCommand::PASTE
563 keyCode:ui::VKEY_V 586 keyCode:ui::VKEY_V
564 domCode:ui::DomCode::US_V 587 domCode:ui::DomCode::US_V
565 eventFlags:ui::EF_CONTROL_DOWN]; 588 eventFlags:ui::EF_CONTROL_DOWN];
566 } 589 }
567 590
568 - (void)selectAll:(id)sender { 591 - (void)selectAll:(id)sender {
569 DCHECK(textInputClient_->IsTextEditCommandEnabled(
570 ui::TextEditCommand::SELECT_ALL));
571 [self handleAction:ui::TextEditCommand::SELECT_ALL 592 [self handleAction:ui::TextEditCommand::SELECT_ALL
572 keyCode:ui::VKEY_A 593 keyCode:ui::VKEY_A
573 domCode:ui::DomCode::US_A 594 domCode:ui::DomCode::US_A
574 eventFlags:ui::EF_CONTROL_DOWN]; 595 eventFlags:ui::EF_CONTROL_DOWN];
575 } 596 }
576 597
577 // BaseView implementation. 598 // BaseView implementation.
578 599
579 // Don't use tracking areas from BaseView. BridgedContentView's tracks 600 // Don't use tracking areas from BaseView. BridgedContentView's tracks
580 // NSTrackingCursorUpdate and Apple's documentation suggests it's incompatible. 601 // NSTrackingCursorUpdate and Apple's documentation suggests it's incompatible.
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 textInputClient_->ConfirmCompositionText(); 1392 textInputClient_->ConfirmCompositionText();
1372 } 1393 }
1373 1394
1374 - (NSArray*)validAttributesForMarkedText { 1395 - (NSArray*)validAttributesForMarkedText {
1375 return @[]; 1396 return @[];
1376 } 1397 }
1377 1398
1378 // NSUserInterfaceValidations protocol implementation. 1399 // NSUserInterfaceValidations protocol implementation.
1379 1400
1380 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { 1401 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
1381 if (!textInputClient_) 1402 ui::TextEditCommand command = GetTextEditCommandForMenuAction([item action]);
1403
1404 if (command == ui::TextEditCommand::INVALID_COMMAND)
1382 return NO; 1405 return NO;
1383 1406
1384 SEL action = [item action]; 1407 if (textInputClient_)
1408 return textInputClient_->IsTextEditCommandEnabled(command);
1385 1409
1386 if (action == @selector(undo:)) 1410 // views::Label does not implement the TextInputClient interface but still
1387 return textInputClient_->IsTextEditCommandEnabled( 1411 // needs to intercept these menu actions.
1388 ui::TextEditCommand::UNDO); 1412 views::FocusManager* focus_manager =
1389 if (action == @selector(redo:)) 1413 hostedView_->GetWidget()->GetFocusManager();
1390 return textInputClient_->IsTextEditCommandEnabled( 1414 if (!focus_manager || !focus_manager->GetFocusedView() ||
1391 ui::TextEditCommand::REDO); 1415 focus_manager->GetFocusedView()->GetClassName() !=
1392 if (action == @selector(cut:)) 1416 views::Label::kViewClassName)
1393 return textInputClient_->IsTextEditCommandEnabled(ui::TextEditCommand::CUT); 1417 return false;
tapted 2016/11/16 08:39:07 nit: false -> NO
karandeepb 2016/11/16 23:47:13 Done.
1394 if (action == @selector(copy:))
1395 return textInputClient_->IsTextEditCommandEnabled(
1396 ui::TextEditCommand::COPY);
1397 if (action == @selector(paste:))
1398 return textInputClient_->IsTextEditCommandEnabled(
1399 ui::TextEditCommand::PASTE);
1400 if (action == @selector(selectAll:))
1401 return textInputClient_->IsTextEditCommandEnabled(
1402 ui::TextEditCommand::SELECT_ALL);
1403 1418
1404 return NO; 1419 views::Label* label =
tapted 2016/11/16 08:39:07 I think this could safely just `return YES`. Right
karandeepb 2016/11/16 23:47:13 Not really, left clicking a label will give focus
1420 static_cast<views::Label*>(focus_manager->GetFocusedView());
1421 return static_cast<ui::SimpleMenuModel::Delegate*>(label)->IsCommandIdEnabled(
tapted 2016/11/16 08:39:07 you could get rid of this static_cast by assigning
karandeepb 2016/11/16 23:47:13 Yeah I remember seeing a thread about this earlier
1422 GetContextMenuCommandForMenuAction([item action]));
1405 } 1423 }
1406 1424
1407 // NSDraggingSource protocol implementation. 1425 // NSDraggingSource protocol implementation.
1408 1426
1409 - (NSDragOperation)draggingSession:(NSDraggingSession*)session 1427 - (NSDragOperation)draggingSession:(NSDraggingSession*)session
1410 sourceOperationMaskForDraggingContext:(NSDraggingContext)context { 1428 sourceOperationMaskForDraggingContext:(NSDraggingContext)context {
1411 return NSDragOperationEvery; 1429 return NSDragOperationEvery;
1412 } 1430 }
1413 1431
1414 - (void)draggingSession:(NSDraggingSession*)session 1432 - (void)draggingSession:(NSDraggingSession*)session
(...skipping 18 matching lines...) Expand all
1433 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point]; 1451 return [hostedView_->GetNativeViewAccessible() accessibilityHitTest:point];
1434 } 1452 }
1435 1453
1436 - (id)accessibilityFocusedUIElement { 1454 - (id)accessibilityFocusedUIElement {
1437 if (!hostedView_) 1455 if (!hostedView_)
1438 return nil; 1456 return nil;
1439 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement]; 1457 return [hostedView_->GetNativeViewAccessible() accessibilityFocusedUIElement];
1440 } 1458 }
1441 1459
1442 @end 1460 @end
OLDNEW
« no previous file with comments | « no previous file | ui/views/controls/label.h » ('j') | ui/views/controls/label_unittest.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698