> {quote:title=Stefan Ineichen wrote:}{quote}
> I have the same issue with XE3. And it is the same with TSaveDialog. I do not have XE5, so does anyone have a solution/bugfix for this?
The following customized version works on 10.9 with XE3
Also, it's safer to call application.processMessages before the TOpendialog.execute (or TSaveDialog) like:
{code}
Application.processMessages;
if ODIALOG.execute
then ...
{code}
{code}
function TPlatformCocoa.DialogSaveFiles(var AFileName: TFileName; const AInitDir, ADefaultExt, AFilter, ATitle: string;
var AFilterIndex: Integer; var AFiles: TStrings; var AOptions: TOpenOptions): Boolean;
var
SaveFile: NSSavePanel;
DefaultExt: string;
Filter: NSArray;
InitialDir: NSURL;
outcome : NSInteger;
function AllocFilterStr(const S: string; var Filter: NSArray): Boolean;
var
input, pattern: string;
FileTypes: array of string;
outcome, aux: TArray<string>;
i, j: Integer;
FileTypesNS: array of Pointer;
NStr: NSString;
LocObj: ILocalObject;
begin
Result := false;
// First, split the string by using '|' as a separator
input := S;
pattern := '\|';
outcome := TRegEx.Split(input, pattern);
pattern := '\*\.';
SetLength(FileTypes, 0);
for i := 0 to length(outcome) - 1 do
begin
if Odd(i) then
if outcome[i] <> '*.*' then
if AnsiLeftStr(outcome[i], 2) = '*.' then
begin
// Split the string by using '*.' as a separator
aux := TRegEx.Split(outcome[i], pattern);
for j := 0 to length(aux) - 1 do
begin
aux[j] := Trim(aux[j]);
if aux[j] <> '' then
begin
//Remove the ';' if necessary
if AnsiEndsStr(';', aux[j]) then
aux[j] := AnsiLeftStr(aux[j], length(aux[j]) - 1);
SetLength(FileTypes, length(FileTypes) + 1);
FileTypes[length(FileTypes) - 1] := aux[j];
end;
end;
end;
end;
// create the NSArray from the FileTypes array
SetLength(FileTypesNS, Length(FileTypes));
for i := 0 to Length(FileTypes) - 1 do
begin
NStr := NSSTR(FileTypes[i]);
if Supports(NStr, ILocalObject, LocObj) then
FileTypesNS[i] := LocObj.GetObjectID;
end;
if length(FileTypes) > 0 then begin
Filter := TNSArray.Wrap(TNSArray.OCClass.arrayWithObjects(@FileTypesNS[0], Length(FileTypes)));
Result := true;
end;
end;
begin
Result := False;
//SaveFile := TNSSavePanel.Create;
SaveFile := TNSSavePanel.Wrap(TNSSavePanel.OCClass.savePanel);
if AInitDir <> '' then
begin
InitialDir := TNSURL.Create;
InitialDir.initFileURLWithPath(NSSTR(AInitDir));
SaveFile.setDirectoryURL(InitialDir);
end;
if AFileName <> '' then
begin
SaveFile.setNameFieldStringValue(NSSTR(AFileName));
end;
if AFilter <> '' then
begin
if AllocFilterStr(AFilter, Filter) then
SaveFile.setAllowedFileTypes(Filter);
end;
if ATitle <> '' then
SaveFile.setTitle(NSSTR(ATitle));
SaveFile.retain;
try
outcome := SaveFile.runModal;
if (FModalStack <> nil) and (FModalStack.Count > 0) then
FRestartModal := True;
if outcome = NSOKButton then
begin
AFileName := UTF8ToString(SaveFile.URL.relativePath.UTF8String);
if DefaultExt <> '' then
if ExtractFileExt(AFileName) = '' then
ChangeFileExt(AFileName, DefaultExt);
Result := True;
end;
finally
SaveFile.release;
end;
end;
{ Dialogs ===============================================================}
function TPlatformCocoa.DialogOpenFiles(var AFileName: TFileName; const AInitDir, ADefaultExt, AFilter, ATitle: string;
var AFilterIndex: Integer; var AFiles: TStrings; var AOptions: TOpenOptions): Boolean;
var
OpenFile: NSOpenPanel;
DefaultExt: string;
Filter: NSArray;
InitialDir: NSURL;
outcome: NSInteger;
I: Integer;
function AllocFilterStr(const S: string; var Filter: NSArray): Boolean;
var
input, pattern: string;
FileTypes: array of string;
outcome, aux: TArray<string>;
i, j: Integer;
FileTypesNS: array of Pointer;
NStr: NSString;
LocObj: ILocalObject;
begin
// First, split the string by using '|' as a separator
Result := false;
input := S;
pattern := '\|';
outcome := TRegEx.Split(input, pattern);
pattern := '\*\.';
SetLength(FileTypes, 0);
for i := 0 to length(outcome) - 1 do
begin
if Odd(i) then
if outcome[i] <> '*.*' then
if AnsiLeftStr(outcome[i], 2) = '*.' then
begin
aux := TRegEx.Split(outcome[i], pattern);
for j := 0 to length(aux) - 1 do
begin
aux[j] := Trim(aux[j]);
if aux[j] <> '' then
begin
if AnsiEndsStr(';', aux[j]) then
aux[j] := AnsiLeftStr(aux[j], length(aux[j]) - 1);
SetLength(FileTypes, length(FileTypes) + 1);
FileTypes[length(FileTypes) - 1] := aux[j];
end;
end;
end;
end;
// create the NSArray from the FileTypes array
SetLength(FileTypesNS, length(FileTypes));
for i := 0 to length(FileTypes) - 1 do
begin
NStr := NSSTR(FileTypes[i]);
if Supports(NStr, ILocalObject, LocObj) then
FileTypesNS[i] := LocObj.GetObjectID;
end;
if length(FileTypes) > 0 then begin
Filter := TNSArray.Wrap(TNSArray.OCClass.arrayWithObjects(@FileTypesNS[0], length(FileTypes)));
result := true;
end;
end;
begin
Result := False;
DefaultExt := ADefaultExt;
OpenFile := TNSOpenPanel.Wrap(TNSOpenPanel.OCClass.openPanel);
OpenFile.setAllowsMultipleSelection(TOpenOption.ofAllowMultiSelect in AOptions);
OpenFile.setCanChooseFiles(True);
// senso added
OpenFile.setCanChooseDirectories(True);
// senso added
OpenFile.setTreatsFilePackagesAsDirectories(True);
// senso added
OpenFile.setResolvesAliases(true);
AFiles.Clear;
if AInitDir <> '' then
begin
InitialDir := TNSURL.Create;
InitialDir.initFileURLWithPath(NSSTR(AInitDir));
OpenFile.setDirectoryURL(InitialDir);
end;
if AFileName <> '' then
begin
OpenFile.setNameFieldStringValue(NSSTR(AFileName));
end;
if AFilter <> '' then
begin
if AllocFilterStr(AFilter, Filter) then
OpenFile.setAllowedFileTypes(Filter);
end;
if ATitle <> '' then
OpenFile.setTitle(NSSTR(ATitle));
OpenFile.retain;
try
outcome := OpenFile.runModal;
if (FModalStack <> nil) and (FModalStack.Count > 0) then
FRestartModal := True;
if outcome = NSOKButton then
begin
for I := 0 to OpenFile.URLs.count - 1 do
AFiles.Add(UTF8ToString(TNSUrl.Wrap(OpenFile.URLs.objectAtIndex(I)).relativePath.UTF8String));
if AFiles.Count > 0 then
AFileName := AFiles[0];
if DefaultExt <> '' then
if ExtractFileExt(AFileName) = '' then
ChangeFileExt(AFileName, DefaultExt);
Result := True;
end;
finally
OpenFile.release;
end;
end;
{code}