Skip to content

Commit 37f657a

Browse files
committed
Improve logic to show nav dialogs on missing file context
This change specifically addresses an issue that commands expecting a file or directory context - and are executed without files - are not getting nav dialog prompt to select file(s)/dir(s) unless OMC_OBJ_PATH is added explicitly to ENVIRONMENT_VARIABLES in command description. It should be implied when the command is specifying ACTIVATION_MODE=act_file, act_folder, act_file_or_folder and related. With this change the command description does not need to add OMC_OBJ_PATH to env vars to trigger nav dialog on missing file context. Commands which don't want this automatic behavior can always opt out with USE_NAV_DIALOG_FOR_MISSING_FILE_CONTEXT=false
1 parent 2272732 commit 37f657a

2 files changed

Lines changed: 99 additions & 82 deletions

File tree

AbracodeFramework/OMCCommandExecutor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@
2727
/// otherwise when the file context is missing the command is not executed
2828
/// if USE_NAV_DIALOG_FOR_MISSING_FILE_CONTEXT is false, the command always executes and no nav dialog is shown
2929

30-
+ (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)inFileName withContext:(id)inContext useNavDialog:(BOOL)useNavDialog delegate:(id)delegate;
30+
+ (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)inFileName withContext:(id)inContext useNavDialog:(BOOL)allowNavDialog delegate:(id)delegate;
3131

3232
@end

AbracodeFramework/OMCCommandExecutor.m

Lines changed: 98 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ void OMCDelegateObserverCallback(OmcObserverMessage inMessage, CFIndex inTaskID,
2929
}
3030
}
3131

32+
static inline
33+
bool IsFileOrFolderActivation(UInt32 activationType)
34+
{
35+
return ((activationType == kActiveFile) ||
36+
(activationType == kActiveFolder) ||
37+
(activationType == kActiveFileOrFolder) ||
38+
(activationType == kActiveFinderWindow) ||
39+
(activationType == kActiveFolderExcludeFinderWindow) ||
40+
(activationType == kActiveFileOrFolderExcludeFinderWindow));
41+
}
42+
3243
@interface OMCCommandExecutor()
3344
+ (CFPropertyListRef)cachedPlistForCommandFile:(NSString *)inFileName;
3445
+ (CFPropertyListRef)cachedPlistForURL:(NSURL *)inURL;
@@ -40,7 +51,7 @@ @implementation OMCCommandExecutor
4051
//when useNavDialog = TRUE, missing file context is obtained from nav dialog
4152
//otherwise when the file context is missing the command is not executed
4253
//if USE_NAV_DIALOG_FOR_MISSING_FILE_CONTEXT is false, the command always executes and no nav dialog is shown
43-
+ (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)inFileName withContext:(id)inContext useNavDialog:(BOOL)useNavDialog delegate:(id)delegate
54+
+ (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)inFileName withContext:(id)inContext useNavDialog:(BOOL)clientAllowsNavDialog delegate:(id)delegate
4455
{
4556
OSStatus error = userCanceledErr;//pessimistic scenario
4657

@@ -61,91 +72,97 @@ + (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)
6172
if( OMCIsValidCommandRef(commandRef) )
6273
{
6374
error = noErr;
64-
65-
UInt32 objectsInfo = kOmcCommandNoSpecialObjects;
66-
OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_CommandObjects, &objectsInfo);
67-
CFArrayRef docList = NULL;
68-
BOOL hasFiles = FALSE;
69-
if( inContext != NULL )
70-
{
75+
76+
// evaluate if we have a path object context for requested path OR file or folder activation
77+
bool hasFiles = false;
78+
if (inContext != NULL)
79+
{
7180
CFTypeID contextType = CFGetTypeID((__bridge CFTypeRef)inContext);
72-
hasFiles = ((contextType == CFArrayGetTypeID()) || (contextType == CFURLGetTypeID()));
73-
}
74-
75-
Boolean useNavDialogForMissingFileContext = true;
76-
UInt32 executionOptions = 0;
77-
OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_ExecutionOptions, &executionOptions);
78-
if( (executionOptions & kExecutionOption_UseNavDialogForMissingFileContext) == 0 )
79-
useNavDialogForMissingFileContext = false;
80-
81-
if( ((objectsInfo & kOmcCommandContainsFileObject) != 0) && !hasFiles && useNavDialogForMissingFileContext )
82-
{
83-
error = userCanceledErr;//command will not execute if we don't specify files
84-
if(useNavDialog)
85-
{
86-
UInt32 activationType = kActiveAlways;
87-
error = OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_ActivationType, &activationType);
88-
89-
CFStringRef theMessage = CFCopyLocalizedStringFromTable(CFSTR("Choose Objects To Process"), CFSTR("Localizable"), "");
90-
91-
NSBundle *appBundle = [NSBundle mainBundle];
92-
NSString *appName = [appBundle objectForInfoDictionaryKey:@"CFBundleName"];
93-
if(appName == NULL)
94-
appName = @"OMCApplet";
95-
96-
switch(activationType)
97-
{
98-
case kActiveFile:
99-
{
100-
docList = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseFiles | kOMCFilePanelAllowMultipleItems );
101-
}
102-
break;
103-
104-
case kActiveFolder:
105-
case kActiveFinderWindow:
106-
case kActiveFolderExcludeFinderWindow:
107-
{
108-
docList = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseDirectories | kOMCFilePanelAllowMultipleItems );
109-
}
110-
break;
111-
112-
default:
113-
{
114-
docList = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseFiles | kOMCFilePanelCanChooseDirectories | kOMCFilePanelAllowMultipleItems );
115-
}
116-
break;
117-
}
118-
CFRelease(theMessage);
119-
error = (docList != NULL) ? noErr : userCanceledErr;
120-
}
121-
122-
if( error == noErr )
123-
{
124-
error = OMCExamineContext( omcExec, commandRef, docList );
125-
126-
if( (error == noErr) && (delegate != nil) && [delegate respondsToSelector:@selector(noteNewRecentDocumentURL:)] )
127-
{
128-
//add to open recent
129-
NSArray<NSURL*> *__weak absoluteURLArray = (__bridge NSArray<NSURL*> *)docList;
130-
for(NSURL *oneFileURL in absoluteURLArray)
131-
{
132-
[delegate noteNewRecentDocumentURL:oneFileURL];
133-
}
134-
}
135-
}
136-
}
137-
else
81+
hasFiles = ((contextType == CFArrayGetTypeID()) || (contextType == CFURLGetTypeID()));
82+
}
83+
84+
bool requiresNavDialog = false;
85+
UInt32 activationType = kActiveAlways;
86+
CFArrayRef selectedFiles = NULL;
87+
88+
if (!hasFiles) // no file context provided. consider carefully whether the command needs files and allows displaying nav dialog
89+
{
90+
// does the command description allows using nav dialogs for missing file context (default = true, must be explicitly disallowed)
91+
UInt32 executionOptions = 0;
92+
OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_ExecutionOptions, &executionOptions);
93+
if ((executionOptions & kExecutionOption_UseNavDialogForMissingFileContext) != 0)
94+
{
95+
// do we have file/dir objects referenced in command or declared in environment variables?
96+
UInt32 objectsInfo = kOmcCommandNoSpecialObjects;
97+
OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_CommandObjects, &objectsInfo);
98+
99+
// does the command activation require file/dir?
100+
OMCGetCommandInfo(omcExec, commandRef, kOmcInfo_ActivationType, &activationType);
101+
requiresNavDialog = ((objectsInfo & kOmcCommandContainsFileObject) != 0) || IsFileOrFolderActivation(activationType);
102+
}
103+
}
104+
105+
if (requiresNavDialog && clientAllowsNavDialog) // all good to go with nav dialog
138106
{
139-
error = OMCExamineContext( omcExec, commandRef, (__bridge CFTypeRef)inContext );
107+
CFStringRef theMessage = CFCopyLocalizedStringFromTable(CFSTR("Choose Objects To Process"), CFSTR("Localizable"), "");
108+
109+
NSBundle *appBundle = [NSBundle mainBundle];
110+
NSString *appName = [appBundle objectForInfoDictionaryKey:@"CFBundleName"];
111+
if(appName == NULL)
112+
appName = @"OMCApplet";
113+
114+
switch(activationType)
115+
{
116+
case kActiveFile:
117+
{
118+
selectedFiles = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseFiles | kOMCFilePanelAllowMultipleItems );
119+
}
120+
break;
121+
122+
case kActiveFolder:
123+
case kActiveFinderWindow:
124+
case kActiveFolderExcludeFinderWindow:
125+
{
126+
selectedFiles = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseDirectories | kOMCFilePanelAllowMultipleItems );
127+
}
128+
break;
129+
130+
default:
131+
{
132+
selectedFiles = CreateCFURLsFromOpenDialog( (__bridge CFStringRef)appName, theMessage, NULL, NULL, kOMCFilePanelCanChooseFiles | kOMCFilePanelCanChooseDirectories | kOMCFilePanelAllowMultipleItems );
133+
}
134+
break;
135+
}
136+
CFRelease(theMessage);
137+
error = (selectedFiles != NULL) ? noErr : userCanceledErr;
140138
}
141-
142-
if(docList != NULL)
139+
else if (requiresNavDialog)
140+
{ // we don't have files, we need the nav dialog but command description explicitly disallows it
141+
error = userCanceledErr; // command will not execute if we don't specify files
142+
}
143+
144+
if (error == noErr)
145+
{
146+
error = OMCExamineContext( omcExec, commandRef, (selectedFiles != NULL) ? selectedFiles : (__bridge CFTypeRef)inContext );
147+
}
148+
149+
if (selectedFiles != NULL)
143150
{
144-
CFRelease(docList);
145-
docList = NULL;
151+
if ((error == noErr) && (delegate != nil) && [delegate respondsToSelector:@selector(noteNewRecentDocumentURL:)])
152+
{
153+
// add to open recent
154+
NSArray<NSURL*> *__weak absoluteURLArray = (__bridge NSArray<NSURL*> *)selectedFiles;
155+
for (NSURL *oneFileURL in absoluteURLArray)
156+
{
157+
[delegate noteNewRecentDocumentURL:oneFileURL];
158+
}
159+
}
160+
161+
CFRelease(selectedFiles);
162+
selectedFiles = NULL;
146163
}
147164

148-
if( error == noErr )
165+
if (error == noErr)
149166
{
150167
// Check if delegate wants to observe task execution
151168
if ((delegate != nil) && [delegate conformsToProtocol:@protocol(OMCObserverDelegate)])
@@ -172,7 +189,7 @@ + (OSStatus)runCommand:(NSString *)inCommandNameOrId forCommandFile:(NSString *)
172189
}
173190
}
174191

175-
OMCReleaseExecutor( omcExec );//safe to release here. task lives on if execution is asynchronous
192+
OMCReleaseExecutor( omcExec ); // safe to release here. task lives on if execution is asynchronous
176193
}
177194

178195
return error;

0 commit comments

Comments
 (0)