GeraldTheGerm
GeraldTheGerm

Reputation: 59

Undo manager with multiple fields

Hello I have an application, it's very basic but has some fields for an address, so city, zip code, state etc...

I want it so the user can undo the content across multiple fields, currently the default undo only works on the field you are using. I am using NSTextFields for my fields.

I assume I need to use UndoManager but I am not sure how to implement it on my fields, my fields have ID's. Is there any documentation on how to do this, none of the fields have any functions - I just grab the data from all of the fields on one of my button events.

I don't know swift so please responsd in Obj-c so I can undertstand what needs to be done.

Upvotes: 0

Views: 79

Answers (1)

Willeke
Willeke

Reputation: 15623

Here's a small example to get you started.

  1. Start with the Xcode macOS App template.
  2. Add the code below to AppDelegate.m.
  3. Add some controls (NSTextField or another subclass of NSControl) to the window.
  4. Connect the action of the controls to controlAction:.
@interface AppDelegate ()

@property (strong) IBOutlet NSWindow *window;

// values before editing, the key is the identifier of the control
@property (strong) NSMutableDictionary *data;

@end


@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    self.data = [[NSMutableDictionary alloc] init];
}

- (void)undoControl:(NSControl *)control oldValue:(id)oldValue newValue:(id)newValue {
    // undo
    NSString *controlID = control.identifier;
    [control setObjectValue:oldValue];
    self.data[controlID] = oldValue;
    if (control.acceptsFirstResponder)
        [self.window makeFirstResponder: control];
    // register redo
    NSLog(@"register redo %@ old:'%@' new:'%@'", controlID, oldValue, newValue);
    [[self.window.undoManager prepareWithInvocationTarget:self] undoControl:control
        oldValue:newValue newValue:oldValue];
}

- (IBAction)controlAction:(NSControl *)control {
    NSString *controlID = control.identifier;
    id oldValue = self.data[controlID];
    id newValue = control.objectValue;
    if (oldValue != newValue && ![oldValue isEqual:newValue]) {
        // register undo
        NSLog(@"register undo %@ old:'%@' new:'%@'", controlID, oldValue, newValue);
        [[self.window.undoManager prepareWithInvocationTarget:self] undoControl:control
            oldValue:oldValue newValue:newValue];
        self.data[controlID] = newValue;
    }
}

@end

Upvotes: 1

Related Questions