aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPEditSheetTextView.h3
-rw-r--r--Source/SPEditSheetTextView.m46
-rw-r--r--Source/SPFieldEditorController.h3
-rw-r--r--Source/SPFieldEditorController.m61
4 files changed, 105 insertions, 8 deletions
diff --git a/Source/SPEditSheetTextView.h b/Source/SPEditSheetTextView.h
index 7c225a78..d6af35ce 100644
--- a/Source/SPEditSheetTextView.h
+++ b/Source/SPEditSheetTextView.h
@@ -25,6 +25,9 @@
#import <Cocoa/Cocoa.h>
@interface SPEditSheetTextView : NSTextView
+{
+ BOOL textWasChanged;
+}
- (unsigned int)characterIndexOfPoint:(NSPoint)aPoint;
- (void)insertFileContentOfFile:(NSString *)aPath;
diff --git a/Source/SPEditSheetTextView.m b/Source/SPEditSheetTextView.m
index 83b691c9..bcde1167 100644
--- a/Source/SPEditSheetTextView.m
+++ b/Source/SPEditSheetTextView.m
@@ -28,7 +28,47 @@
@implementation SPEditSheetTextView
-- (void) keyDown:(NSEvent *)theEvent
+- (IBAction)undo:(id)sender
+{
+ textWasChanged = NO;
+ [[self undoManager] undo];
+ // Due to the undoManager implementation it could happen that
+ // an action will be recoreded which actually didn't change the
+ // text buffer. That's why repeat undo.
+ if(!textWasChanged) [[self undoManager] undo];
+}
+
+- (IBAction)redo:(id)sender
+{
+ textWasChanged = NO;
+ [[self undoManager] redo];
+ // Due to the undoManager implementation it could happen that
+ // an action will be recoreded which actually didn't change the
+ // text buffer. That's why repeat redo.
+ if(!textWasChanged) [[self undoManager] redo];
+}
+
+/*
+ * Validate undo and redo menu items
+ */
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
+{
+
+ if ([menuItem action] == @selector(undo:)) {
+ return ([[self undoManager] canUndo]);
+ }
+ if ([menuItem action] == @selector(redo:)) {
+ return ([[self undoManager] canRedo]);
+ }
+ return YES;
+}
+
+- (void)textDidChange:(NSNotification *)aNotification
+{
+ textWasChanged = YES;
+}
+
+- (void)keyDown:(NSEvent *)theEvent
{
long allFlags = (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask);
@@ -62,9 +102,9 @@
return;
}
}
-
+
[super keyDown: theEvent];
-
+
}
/*
diff --git a/Source/SPFieldEditorController.h b/Source/SPFieldEditorController.h
index a330108e..e5fbb0e3 100644
--- a/Source/SPFieldEditorController.h
+++ b/Source/SPFieldEditorController.h
@@ -51,10 +51,13 @@
int counter;
unsigned long long maxTextLength;
BOOL editTextViewWasChanged;
+ BOOL allowUndo;
NSUserDefaults *prefs;
int editSheetReturnCode;
+
+ NSUndoManager *esUndoManager;
}
- (IBAction)closeEditSheet:(id)sender;
diff --git a/Source/SPFieldEditorController.m b/Source/SPFieldEditorController.m
index 739e5b08..b2193b32 100644
--- a/Source/SPFieldEditorController.m
+++ b/Source/SPFieldEditorController.m
@@ -51,7 +51,7 @@
// Allow the user to enter cmd+return to close the edit sheet in addition to fn+return
[editSheetOkButton setKeyEquivalentModifierMask:NSCommandKeyMask];
- // [editTextView setFormatter:[[SPDataCellFormatter new] autorelease]];
+ allowUndo = NO;
}
return self;
@@ -60,6 +60,7 @@
- (void)dealloc
{
+ if ( esUndoManager ) [esUndoManager release];
if ( sheetEditData ) [sheetEditData release];
[super dealloc];
}
@@ -209,11 +210,43 @@
// wait for editSheet
NSModalSession session = [NSApp beginModalSessionForWindow:editSheet];
- int response;
+ int cycleCounter = 0;
for (;;) {
- if (response = [NSApp runModalSession:session] != NSRunContinuesResponse
+
+ cycleCounter++;
+
+ // Allow undo grouping if user typed a ' ' (for word level undo)
+ // or a RETURN
+ if([[NSApp currentEvent] type] == NSKeyDown
+ && (
+ [[[NSApp currentEvent] charactersIgnoringModifiers] isEqualToString:@" "]
+ || [[NSApp currentEvent] keyCode] == 36
+ )
+ )
+ cycleCounter=100;
+
+ // After 5 run loops (fast writing forms longer blocks)
+ // or the user typed a ' ' or RETURN and the textView was changed (allowUndo)
+ // form an undo group
+ if(cycleCounter>5 && allowUndo && ![esUndoManager isUndoing] && ![esUndoManager isRedoing]) {
+ cycleCounter=0;
+ allowUndo = NO;
+ while([esUndoManager groupingLevel] > 0) {
+ [esUndoManager endUndoGrouping];
+ cycleCounter++;
+ }
+ while([esUndoManager groupingLevel] < cycleCounter)
+ [esUndoManager beginUndoGrouping];
+
+ cycleCounter = 0;
+ }
+
+ // Break the run loop if editSheet was closed
+ if ([NSApp runModalSession:session] != NSRunContinuesResponse
|| ![editSheet isVisible])
break;
+
+ // Execute code on DefaultRunLoop (like displaying a tooltip)
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]];
@@ -228,6 +261,17 @@
return ( editSheetReturnCode && isEditable ) ? [sheetEditData retain] : nil;
}
+/*
+ * Establish and return an UndoManager for editTextView
+ */
+- (NSUndoManager*)undoManagerForTextView:(NSTextView*)aTextView
+{
+ if (!esUndoManager)
+ esUndoManager = [[NSUndoManager alloc] init];
+
+ return esUndoManager;
+}
+
- (IBAction)closeEditSheet:(id)sender
{
@@ -235,6 +279,7 @@
// Validate the sheet data before saving them.
// - for max text length select the part which won't be saved
+ // and suppress closing the sheet
if(sender == editSheetOkButton) {
if (maxTextLength > 0 && [[editTextView textStorage] length] > maxTextLength) {
[editTextView setSelectedRange:NSMakeRange(maxTextLength, [[editTextView textStorage] length] - maxTextLength)];
@@ -741,9 +786,8 @@
if ( [aTextView methodForSelector:aSelector] == [aTextView methodForSelector:@selector(insertNewline:)] &&
[[[NSApp currentEvent] characters] isEqualToString:@"\003"] )
{
- // [NSApp stopModalWithCode:1];
- // return YES;
[self closeEditSheet:editSheetOkButton];
+ return YES;
}
else
return NO;
@@ -751,5 +795,12 @@
return NO;
}
+- (void)textDidChange:(NSNotification *)aNotification
+{
+ // Allow undo grouping only if the text buffer was really changed
+ allowUndo = YES;
+}
+
+
@end