Revision: 29281
http://sourceforge.net/p/bibdesk/svn/29281
Author: hofman
Date: 2025-07-17 16:36:29 +0000 (Thu, 17 Jul 2025)
Log Message:
-----------
Get commit errors from text fields in editorr separately from fake delegate
methods. Present the errors in the control delegate methods. Also use the
errors in commitEditingAndReturnError:, so it does not display the errors in a
sheet or dialog.
Modified Paths:
--------------
trunk/bibdesk/BDSKEditor.m
Modified: trunk/bibdesk/BDSKEditor.m
===================================================================
--- trunk/bibdesk/BDSKEditor.m 2025-07-15 09:33:52 UTC (rev 29280)
+++ trunk/bibdesk/BDSKEditor.m 2025-07-17 16:36:29 UTC (rev 29281)
@@ -124,6 +124,9 @@
- (void)fileURLDidChange:(NSNotification *)notification;
- (void)needsToBeFiledDidChange:(NSNotification *)notification;
+- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string
errorDescription:(NSString *)errorString error:(NSError **)error;
+- (BOOL)control:(NSControl *)control isValidObject:(id)obj error:(NSError
**)error;
+
- (void)recordChangingField:(NSString *)fieldName toValue:(NSString *)value;
- (void)openParentItemForField:(NSString *)field;
@@ -409,7 +412,50 @@
- (BOOL)commitEditing
{
- return [self commitEditingAndReturnError:NULL];
+ NSResponder *firstResponder = [[self window] firstResponder];
+
+ /*
+ Need to finalize text field cells being edited or the abstract/annote
text views, since the
+ text views bypass the normal undo mechanism for speed, and won't cause
the doc to be marked
+ dirty on subsequent edits.
+ */
+ if([firstResponder isKindOfClass:[NSText class]]){
+
+ NSTextView *textView = (NSTextView *)firstResponder;
+ NSInteger editedRow = -1;
+ NSArray *selection = [textView selectedRanges];
+ if ([textView isFieldEditor]) {
+ firstResponder = (NSResponder *)[textView delegate];
+ editedRow = [tableView rowForView:textView];
+ }
+
+ editorFlags.didSetupFields = NO; // if we we rebuild the fields, the
selection will become meaningless
+
+ // check textviews for balanced braces as needed
+ if (currentEditedView && [self validateCurrentEditedView] == NO)
+ return NO;
+
+ // commit edits (formatters may refuse to allow this)
+ if ([[self window] makeFirstResponder:[self window]] == NO)
+ return NO;
+
+ // for inherited fields, we should do something here to make sure the
user doesn't have to go through the warning sheet
+
+ if (editorFlags.didSetupFields == NO || editedRow == -1) {
+ if (editedRow != -1) {
+ if (editedRow < [tableView numberOfRows]) {
+ [tableView editColumn:1 row:editedRow withEvent:nil
select:NO];
+ [(NSTextView *)[[self textFieldAtRow:editedRow]
currentEditor] setSafeSelectedRanges:selection];
+ }
+ } else if ([[self window] makeFirstResponder:firstResponder]) {
+ if ([firstResponder isKindOfClass:[NSTextField class]])
+ textView = (NSTextView *)[(NSTextField *)firstResponder
currentEditor];
+ [textView setSafeSelectedRanges:selection];
+ }
+ }
+
+ }
+ return YES;
}
- (BOOL)commitEditingAndReturnError:(NSError **)error
@@ -425,24 +471,69 @@
if([firstResponder isKindOfClass:[NSText class]]){
NSTextView *textView = (NSTextView *)firstResponder;
+ NSTextField *textField = nil;
NSInteger editedRow = -1;
NSArray *selection = [textView selectedRanges];
if ([textView isFieldEditor]) {
firstResponder = (NSResponder *)[textView delegate];
+ if ([firstResponder isKindOfClass:[NSTextField class]])
+ textField = (NSTextField *)firstResponder;
editedRow = [tableView rowForView:textView];
}
- editorFlags.didSetupFields = NO; // if we we rebuild the
fields, the selection will become meaningless
-
- // check textviews for balanced braces as needed
- if (currentEditedView && [self validateCurrentEditedView] == NO) {
- if (error)
- *error = [NSError localErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Failed to commit edits", @"Error
message")];
+ if (textField) {
+
+ BOOL valid = YES;
+ NSString *obj = nil;
+ NSFormatter *formatter = [textField formatter];
+
+ if (formatter) {
+ NSString *errorString = nil;
+ NSString *string = [textView string];
+ valid = [formatter getObjectValue:&obj forString:string
errorDescription:&errorString];
+ if (valid == NO) {
+ valid = [self control:textField
didFailToFormatString:string errorDescription:errorString error:error];
+ if (valid == NO)
+ return NO;
+ }
+ } else {
+ obj = [textView string];
+ }
+ valid = [self control:textField isValidObject:obj error:error];
+
+ if (valid == NO) {
+ if (error && [*error localizedRecoveryOptions]) {
+ // no recovery possible, so just make it an unrecoverable
error
+ NSError *err = [NSError
mutableLocalErrorWithCode:kBDSKFailedToCommit localizedDescription:[*error
localizedDescription]];
+ NSString *errString = [*error localizedRecoverySuggestion];
+ NSRange r = [errString rangeOfString:@"."];
+ if (r.location != NSNotFound)
+ errString = [errString substringToIndex:NSMaxRange(r)];
+ [err setValue:errString
forKey:NSLocalizedRecoverySuggestionErrorKey];
+ *error = err;
+ }
+ return NO;
+ }
+
+ } else if (currentEditedView && [self validateCurrentEditedView] ==
NO) {
+ // the string of the edited textView has unbalanced braces
+
+ if (error) {
+ NSError *err = [NSError
mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Failed to commit edits", @"Error
message")];
+ [err setValue:NSLocalizedString(@"The value you entered
contains unbalanced braces and cannot be saved.", @"Informative text in alert
dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
+ *error = err;
+ }
return NO;
+
}
+ // commit should now succeed without errors
+
+ editorFlags.didSetupFields = NO; // if we we rebuild the
fields, the selection will become meaningless
+
// commit edits (formatters may refuse to allow this)
if ([[self window] makeFirstResponder:[self window]] == NO) {
+ // should not be reached, we should have found errors above
if (error)
*error = [NSError localErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Failed to commit edits", @"Error
message")];
return NO;
@@ -457,8 +548,8 @@
[(NSTextView *)[[self textFieldAtRow:editedRow]
currentEditor] setSafeSelectedRanges:selection];
}
} else if ([[self window] makeFirstResponder:firstResponder]) {
- if ([firstResponder isKindOfClass:[NSTextField class]])
- textView = (NSTextView *)[(NSTextField *)firstResponder
currentEditor];
+ if (textField)
+ textView = (NSTextView *)[textField currentEditor];
[textView setSafeSelectedRanges:selection];
}
}
@@ -1899,23 +1990,21 @@
// Don't show an annoying warning. This fails only when invalid cite key
characters are used, which are simply removed by the formatter.
}
-// send by the formatter when formatting in getObjectValue... failed
-- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)aString
errorDescription:(NSString *)error{
+- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)aString
errorDescription:(NSString *)errorString error:(NSError **)error {
if (editorFlags.isEditable == NO)
return YES;
- BOOL accept = NO;
+ NSError *err = nil;
- if (nil == error) {
+ if (nil == errorString) {
// shouldn't get here
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert
dialog when entering an invalid value")];
NSLog(@"%@:%d formatter failed for unknown reason",
__FILENAMEASNSSTRING__, __LINE__);
} else if (control == citeKeyField) {
// !!! may have to revisit this with strict invalid keys?
// this may occur if the cite key formatter fails to format
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Cite Key", @"Message
in alert dialog when enetring invalid cite key")];
- [alert setInformativeText:error];
- [alert beginSheetModalForWindow:[self window] completionHandler:NULL];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Cite Key", @"Message in alert
dialog when enetring invalid cite key")];
+ [err setValue:errorString
forKey:NSLocalizedRecoverySuggestionErrorKey];
} else {
@@ -1925,36 +2014,56 @@
NSString *fieldName = [fields objectAtIndex:row];
if ([fieldName isEqualToString:BDSKCrossrefString]) {
// this may occur if the cite key formatter fails to format
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Crossref
Key", @"Message in alert dialog when entering invalid Crossref key")];
- [alert setInformativeText:error];
-
- [alert beginSheetModalForWindow:[self window]
completionHandler:NULL];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Crossref Key", @"Message in
alert dialog when entering invalid Crossref key")];
+ [err setValue:errorString
forKey:NSLocalizedRecoverySuggestionErrorKey];
} else if ([fieldName isCitationField]) {
// this may occur if the citation formatter fails to format
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Citation
Key", @"Message in alert dialog when entering invalid Crossref key")];
- [alert setInformativeText:error];
-
- [alert beginSheetModalForWindow:[self window]
completionHandler:NULL];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Citation Key", @"Message in
alert dialog when entering invalid Crossref key")];
+ [err setValue:errorString
forKey:NSLocalizedRecoverySuggestionErrorKey];
} else if (NO == [tableCellFormatter editAsComplexString]) {
// this is a simple string, an error means that there are
unbalanced braces
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Value",
@"Message in alert dialog when entering an invalid value")];
- [alert setInformativeText:NSLocalizedString(@"The value you
entered contains unbalanced braces and cannot be saved.", @"Informative text in
alert dialog")];
-
- [alert beginSheetModalForWindow:[self window]
completionHandler:NULL];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert
dialog when entering an invalid value")];
+ [err setValue:NSLocalizedString(@"The value you entered
contains unbalanced braces and cannot be saved.", @"Informative text in alert
dialog") forKey:NSLocalizedRecoverySuggestionErrorKey];
+ } else {
+ err = [NSError
mutableLocalErrorWithCode:kBDSKComplexStringError
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert
dialog when entering an invalid value")];
+ [err setValue:errorString
forKey:NSLocalizedRecoverySuggestionErrorKey];
}
}
- }
+ }
+
+ if (error)
+ *error = err;
+ return NO;
+}
+
+// send by the formatter when formatting in getObjectValue... failed
+- (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)aString
errorDescription:(NSString *)error{
+ if (editorFlags.isEditable == NO)
+ return YES;
+
+ NSError *err = nil;
+ BOOL accept = [self control:control didFailToFormatString:aString
errorDescription:error error:&err];
+
+ if (accept == NO) {
+ if (err && [err code] != kBDSKComplexStringError)
+ [self presentError:err modalForWindow:[self window] delegate:nil
didPresentSelector:NULL contextInfo:NULL];
+ else
+ NSBeep();
+ }
+
return accept;
}
-- (BOOL)control:(NSControl *)control isValidObject:(id)obj {
+- (BOOL)attemptRecoveryFromError:(NSError *)error
optionIndex:(NSUInteger)recoveryOptionIndex {
+ return (recoveryOptionIndex == 0);
+}
+
+- (BOOL)control:(NSControl *)control isValidObject:(id)obj error:(NSError
**)error {
if (editorFlags.isEditable == NO)
return YES;
BOOL isValid = YES;
+ NSError *err = nil;
if (control == citeKeyField) {
@@ -1965,21 +2074,12 @@
// check for fragile invalid characters, as the formatter doesn't do
this
if (r.location != NSNotFound) {
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Value",
@"Message in alert dialog when entering an invalid value")];
- [alert setInformativeText:NSLocalizedString(@"The cite key you
entered contains characters that could be invalid in TeX. Do you want to keep
them or remove them?", @"Informative text in alert dialog")];
- [alert addButtonWithTitle:NSLocalizedString(@"Remove", @"Button
title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Keep", @"Button
title")];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert
dialog when entering an invalid value")];
+ [err setValue:NSLocalizedString(@"The cite key you entered
contains characters that could be invalid in TeX. Do you want to keep them or
remove them?", @"Informative text in alert dialog")
forKey:NSLocalizedRecoverySuggestionErrorKey];
+ [err setValue:self forKey:NSRecoveryAttempterErrorKey];
+ [err setValue:@[NSLocalizedString(@"Remove", @"Button title"),
NSLocalizedString(@"Keep", @"Button title")]
forKey:NSLocalizedRecoveryOptionsErrorKey];
+ isValid = NO;
- NSInteger rv = [alert runModal];
-
- if (rv == NSAlertFirstButtonReturn) {
- [control setStringValue:[obj
stringByReplacingCharactersInSet:invalidSet withString:@""]];
- isValid = NO;
- } else {
- [citeKeyField setStringValue:[control stringValue]];
- }
-
} else {
// check whether we won't crossref to the new citekey
@@ -1990,11 +2090,8 @@
message = NSLocalizedString(@"Cannot set this cite key as this
would lead to a crossreff chain.", @"Informative text in alert dialog");
if (message) {
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Value",
@"Message in alert dialog when entering an invalid value")];
- [alert setInformativeText:message];
-
- [alert beginSheetModalForWindow:[self window]
completionHandler:NULL];
+ err = [NSError mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Value", @"Message in alert
dialog when entering an invalid value")];
+ [err setValue:message
forKey:NSLocalizedRecoverySuggestionErrorKey];
isValid = NO;
}
}
@@ -2019,20 +2116,37 @@
message = NSLocalizedString(@"Cannot set the Crossref
field, as the current item is cross referenced.", @"Informative text in alert
dialog");
if (message) {
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Invalid Crossref
Value", @"Message in alert dialog when entering an invalid Crossref key")];
- [alert setInformativeText:message];
-
- [alert beginSheetModalForWindow:[self window]
completionHandler:NULL];
+ err = [NSError
mutableLocalErrorWithCode:kBDSKFailedToCommit
localizedDescription:NSLocalizedString(@"Invalid Crossref Value", @"Message in
alert dialog when entering an invalid Crossref key")];
+ [err setValue:message
forKey:NSLocalizedRecoverySuggestionErrorKey];
isValid = NO;
}
}
}
}
-
- return isValid;
+
+ if (isValid == NO && error)
+ *error = err;
+ return isValid;
}
+- (BOOL)control:(NSControl *)control isValidObject:(id)obj {
+ NSError *err = nil;
+ BOOL isValid = [self control:control isValidObject:obj error:&err];
+
+ if (isValid)
+ return YES;
+
+ isValid = [self presentError:err];
+
+ if (control == citeKeyField && [err localizedRecoveryOptions] && isValid
== NO) {
+ // user said to remove fragile characters
+ NSCharacterSet *invalidSet = [[BDSKTypeManager sharedManager]
fragileCiteKeyCharacterSet];
+ [control setStringValue:[obj
stringByReplacingCharactersInSet:invalidSet withString:@""]];
+ }
+
+ return isValid;
+}
+
- (void)controlTextDidEndEditing:(NSNotification *)notification{
[self setEditing:NO];
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
_______________________________________________
Bibdesk-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/bibdesk-commit