OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "ios/clean/chrome/browser/ui/context_menu/context_menu_view_controller.h
" | 5 #import "ios/clean/chrome/browser/ui/context_menu/context_menu_view_controller.h
" |
6 | 6 |
| 7 #include "base/logging.h" |
| 8 #import "ios/clean/chrome/browser/ui/context_menu/context_menu_context.h" |
| 9 |
7 #if !defined(__has_feature) || !__has_feature(objc_arc) | 10 #if !defined(__has_feature) || !__has_feature(objc_arc) |
8 #error "This file requires ARC support." | 11 #error "This file requires ARC support." |
9 #endif | 12 #endif |
10 | 13 |
11 namespace { | 14 namespace { |
12 // Typedef the block parameter for UIAlertAction for readability. | 15 // Typedef the block parameter for UIAlertAction for readability. |
13 typedef void (^AlertActionHandler)(UIAlertAction*); | 16 typedef void (^AlertActionHandler)(UIAlertAction*); |
| 17 // Sends |commands| to |dispatcher| using |context| as the menu context. |
| 18 void DispatchContextMenuCommands(const std::vector<SEL>& commands, |
| 19 id dispatcher, |
| 20 ContextMenuContext* context) { |
| 21 DCHECK(dispatcher); |
| 22 DCHECK(context); |
| 23 for (SEL command : commands) { |
| 24 IMP command_imp = [dispatcher methodForSelector:command]; |
| 25 DCHECK(command_imp); |
| 26 command_imp(dispatcher, command, context); |
| 27 } |
| 28 } |
14 } | 29 } |
15 | 30 |
16 @interface ContextMenuViewController () | 31 @interface ContextMenuViewController () |
17 // Object to which command messages will be sent. | 32 // The dispatcher passed on initialization. |
18 @property(nonatomic, weak) id dispatcher; | 33 @property(nonatomic, readonly, weak) id<ContextMenuCommands> dispatcher; |
| 34 // The context passed on initialization. |
| 35 @property(nonatomic, strong) ContextMenuContext* context; |
| 36 |
| 37 // Creates an UIAlertAction for |item| using |style| to manage the action's |
| 38 // appearance. |
| 39 - (UIAlertAction*)alertActionForItem:(ContextMenuItem*)item |
| 40 style:(UIAlertActionStyle)style; |
| 41 |
19 @end | 42 @end |
20 | 43 |
21 @implementation ContextMenuViewController | 44 @implementation ContextMenuViewController |
22 @synthesize dispatcher = _dispatcher; | 45 @synthesize dispatcher = _dispatcher; |
| 46 @synthesize context = _context; |
23 | 47 |
24 - (instancetype)initWithDispatcher:(id)dispatcher { | 48 - (instancetype)initWithDispatcher:(id<ContextMenuCommands>)dispatcher { |
25 self = | 49 self = |
26 [[self class] alertControllerWithTitle:nil | 50 [[self class] alertControllerWithTitle:nil |
27 message:nil | 51 message:nil |
28 preferredStyle:UIAlertControllerStyleActionSheet]; | 52 preferredStyle:UIAlertControllerStyleActionSheet]; |
29 if (self) { | 53 if (self) { |
| 54 DCHECK(dispatcher); |
30 _dispatcher = dispatcher; | 55 _dispatcher = dispatcher; |
31 } | 56 } |
32 return self; | 57 return self; |
33 } | 58 } |
34 | 59 |
35 #pragma mark - ContextMenuConsumer | 60 #pragma mark - ContextMenuConsumer |
36 | 61 |
| 62 - (void)setContextMenuContext:(ContextMenuContext*)context { |
| 63 DCHECK(context); |
| 64 self.context = context; |
| 65 } |
| 66 |
37 - (void)setContextMenuTitle:(NSString*)title { | 67 - (void)setContextMenuTitle:(NSString*)title { |
38 self.title = title; | 68 self.title = title; |
39 } | 69 } |
40 | 70 |
41 - (void)setContextMenuItems:(NSArray<ContextMenuItem*>*)items { | 71 - (void)setContextMenuItems:(NSArray<ContextMenuItem*>*)items |
| 72 cancelItem:(ContextMenuItem*)cancelItem { |
| 73 // Add an alert action for each item in |items|, then add |cancelItem|. |
42 for (ContextMenuItem* item in items) { | 74 for (ContextMenuItem* item in items) { |
43 // Create a block that sends the invocation passed in with the item's | 75 [self addAction:[self alertActionForItem:item |
44 // configuration to the dispatcher. | 76 style:UIAlertActionStyleDefault]]; |
45 AlertActionHandler handler = ^(UIAlertAction* action) { | |
46 [item.command invokeWithTarget:self.dispatcher]; | |
47 }; | |
48 [self addAction:[UIAlertAction actionWithTitle:item.title | |
49 style:UIAlertActionStyleDefault | |
50 handler:handler]]; | |
51 } | 77 } |
| 78 [self addAction:[self alertActionForItem:cancelItem |
| 79 style:UIAlertActionStyleCancel]]; |
| 80 } |
52 | 81 |
53 // Always add a cancel action. | 82 #pragma mark - |
54 [self addAction:[UIAlertAction actionWithTitle:@"Cancel" | 83 |
55 style:UIAlertActionStyleCancel | 84 - (UIAlertAction*)alertActionForItem:(ContextMenuItem*)item |
56 handler:nil]]; | 85 style:(UIAlertActionStyle)style { |
| 86 DCHECK(item); |
| 87 // Create a block that dispatches |item|'s ContextMenuCommands. |
| 88 AlertActionHandler handler = ^(UIAlertAction* action) { |
| 89 DispatchContextMenuCommands(item.commands, self.dispatcher, self.context); |
| 90 }; |
| 91 return [UIAlertAction actionWithTitle:item.title style:style handler:handler]; |
57 } | 92 } |
58 | 93 |
59 @end | 94 @end |
OLD | NEW |