Flutter Engine
 
Loading...
Searching...
No Matches
FlutterUndoManagerPlugin.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#pragma mark - UndoManager channel method names.
8static NSString* const kSetUndoStateMethod = @"UndoManager.setUndoState";
9
10#pragma mark - Undo State field names
11static NSString* const kCanUndo = @"canUndo";
12static NSString* const kCanRedo = @"canRedo";
13
15@property(nonatomic, weak, readonly) id<FlutterUndoManagerDelegate> undoManagerDelegate;
16
17// When the delegate is `FlutterEngine` this will be the `FlutterViewController`'s undo manager.
18// Strongly retain to ensure this target's actions are completely removed during dealloc.
19@property(nonatomic) NSUndoManager* undoManager;
20@end
21
22@implementation FlutterUndoManagerPlugin
23
24- (instancetype)initWithDelegate:(id<FlutterUndoManagerDelegate>)undoManagerDelegate {
25 self = [super init];
26
27 if (self) {
28 _undoManagerDelegate = undoManagerDelegate;
29 }
30
31 return self;
32}
33
34- (void)dealloc {
35 [_undoManager removeAllActionsWithTarget:self];
36}
37
38- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
39 NSString* method = call.method;
40 id args = call.arguments;
41 if ([method isEqualToString:kSetUndoStateMethod]) {
42 self.undoManager = self.undoManagerDelegate.undoManager;
43 [self setUndoState:args];
44 result(nil);
45 } else {
47 }
48}
49
50- (void)resetUndoManager {
51 [self.undoManager removeAllActionsWithTarget:self];
52}
53
54- (void)registerUndoWithDirection:(FlutterUndoRedoDirection)direction {
55 NSUndoManager* undoManager = self.undoManager;
56 [undoManager beginUndoGrouping];
57 [undoManager registerUndoWithTarget:self
58 handler:^(FlutterUndoManagerPlugin* target) {
59 // Register undo with opposite direction.
60 FlutterUndoRedoDirection newDirection =
61 (direction == FlutterUndoRedoDirectionRedo)
62 ? FlutterUndoRedoDirectionUndo
63 : FlutterUndoRedoDirectionRedo;
64 [target registerUndoWithDirection:newDirection];
65 // Invoke method on delegate.
66 [target.undoManagerDelegate handleUndoWithDirection:direction];
67 }];
68 [undoManager endUndoGrouping];
69}
70
71- (void)registerRedo {
72 NSUndoManager* undoManager = self.undoManager;
73 [undoManager beginUndoGrouping];
74 [undoManager registerUndoWithTarget:self
75 handler:^(id target) {
76 // Register undo with opposite direction.
77 [target registerUndoWithDirection:FlutterUndoRedoDirectionRedo];
78 }];
79 [undoManager endUndoGrouping];
80 [undoManager undo];
81}
82
83- (void)setUndoState:(NSDictionary*)dictionary {
84 NSUndoManager* undoManager = self.undoManager;
85 BOOL groupsByEvent = undoManager.groupsByEvent;
86 undoManager.groupsByEvent = NO;
87 BOOL canUndo = [dictionary[kCanUndo] boolValue];
88 BOOL canRedo = [dictionary[kCanRedo] boolValue];
89
90 [self resetUndoManager];
91
92 if (canUndo) {
93 [self registerUndoWithDirection:FlutterUndoRedoDirectionUndo];
94 }
95 if (canRedo) {
96 [self registerRedo];
97 }
98 UIView<UITextInput>* textInputView = self.undoManagerDelegate.activeTextInputView;
99 if (textInputView != nil) {
100 // This is needed to notify the iPadOS keyboard that it needs to update the
101 // state of the UIBarButtons. Otherwise, the state changes to NSUndoManager
102 // will not show up until the next keystroke (or other trigger).
103 UITextInputAssistantItem* assistantItem = textInputView.inputAssistantItem;
104 assistantItem.leadingBarButtonGroups = assistantItem.leadingBarButtonGroups;
105 }
106 undoManager.groupsByEvent = groupsByEvent;
107}
108
109@end
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
static NSString *const kSetUndoStateMethod
static NSString *const kCanUndo
static NSString *const kCanRedo
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
int BOOL