forked from flutter/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFlutterUndoManagerPlugin.mm
More file actions
111 lines (92 loc) · 3.92 KB
/
FlutterUndoManagerPlugin.mm
File metadata and controls
111 lines (92 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterUndoManagerPlugin.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h"
#pragma mark - UndoManager channel method names.
static NSString* const kSetUndoStateMethod = @"UndoManager.setUndoState";
#pragma mark - Undo State field names
static NSString* const kCanUndo = @"canUndo";
static NSString* const kCanRedo = @"canRedo";
@interface FlutterUndoManagerPlugin ()
@property(nonatomic, weak, readonly) id<FlutterUndoManagerDelegate> undoManagerDelegate;
@property(nonatomic, readonly) NSUndoManager* undoManager;
@end
@implementation FlutterUndoManagerPlugin
- (instancetype)initWithDelegate:(id<FlutterUndoManagerDelegate>)undoManagerDelegate {
self = [super init];
if (self) {
_undoManagerDelegate = undoManagerDelegate;
}
return self;
}
- (void)dealloc {
[_undoManagerDelegate.undoManager removeAllActionsWithTarget:self];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
NSString* method = call.method;
id args = call.arguments;
if ([method isEqualToString:kSetUndoStateMethod]) {
[self setUndoState:args];
result(nil);
} else {
result(FlutterMethodNotImplemented);
}
}
- (NSUndoManager*)undoManager {
return self.undoManagerDelegate.undoManager;
}
- (void)resetUndoManager {
[self.undoManager removeAllActionsWithTarget:self];
}
- (void)registerUndoWithDirection:(FlutterUndoRedoDirection)direction {
NSUndoManager* undoManager = self.undoManager;
[undoManager beginUndoGrouping];
[undoManager registerUndoWithTarget:self
handler:^(FlutterUndoManagerPlugin* target) {
// Register undo with opposite direction.
FlutterUndoRedoDirection newDirection =
(direction == FlutterUndoRedoDirectionRedo)
? FlutterUndoRedoDirectionUndo
: FlutterUndoRedoDirectionRedo;
[target registerUndoWithDirection:newDirection];
// Invoke method on delegate.
[target.undoManagerDelegate handleUndoWithDirection:direction];
}];
[undoManager endUndoGrouping];
}
- (void)registerRedo {
NSUndoManager* undoManager = self.undoManager;
[undoManager beginUndoGrouping];
[undoManager registerUndoWithTarget:self
handler:^(id target) {
// Register undo with opposite direction.
[target registerUndoWithDirection:FlutterUndoRedoDirectionRedo];
}];
[undoManager endUndoGrouping];
[undoManager undo];
}
- (void)setUndoState:(NSDictionary*)dictionary {
NSUndoManager* undoManager = [self undoManager];
BOOL groupsByEvent = undoManager.groupsByEvent;
undoManager.groupsByEvent = NO;
BOOL canUndo = [dictionary[kCanUndo] boolValue];
BOOL canRedo = [dictionary[kCanRedo] boolValue];
[self resetUndoManager];
if (canUndo) {
[self registerUndoWithDirection:FlutterUndoRedoDirectionUndo];
}
if (canRedo) {
[self registerRedo];
}
UIView<UITextInput>* textInputView = self.undoManagerDelegate.activeTextInputView;
if (textInputView != nil) {
// This is needed to notify the iPadOS keyboard that it needs to update the
// state of the UIBarButtons. Otherwise, the state changes to NSUndoManager
// will not show up until the next keystroke (or other trigger).
UITextInputAssistantItem* assistantItem = textInputView.inputAssistantItem;
assistantItem.leadingBarButtonGroups = assistantItem.leadingBarButtonGroups;
}
undoManager.groupsByEvent = groupsByEvent;
}
@end