lazarus-ccr/components/iphonelazext/iphoneextoptions.pas
skalogryz 9941cd6ca4 iphonelazext: added nib files support
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1205 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2010-04-25 08:47:00 +00:00

511 lines
14 KiB
ObjectPascal

{
*****************************************************************************
* *
* This file is part of the iPhone Laz Extension *
* *
* See the file COPYING.modifiedLGPL.txt, included in this distribution, *
* for details about the copyright. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
*****************************************************************************
}
unit iPhoneExtOptions;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, IDEOptionsIntf, LazIDEIntf, ProjectIntf, iPhoneBundle, DOM, XMLRead, XMLConf, PlistFile;
type
{ TiPhoneProjectOptions }
TiPhoneProjectOptions = class(TAbstractIDEProjectOptions)
private
fisiPhone : Boolean;
fAppID : String;
fSDK : String;
DataWritten : Boolean;
fSpaceName : String;
fResourceDir : String;
fExcludeMask : String;
fMainNib : String;
public
constructor Create;
class function GetGroupCaption: String; override;
class function GetInstance: TAbstractIDEOptions; override;
function Load: Boolean;
function Save: Boolean;
procedure Reset;
property isIPhoneApp: Boolean read fisIPhone write fisIPhone;
property SDK: String read fSDK write fSDK;
property AppID: String read fAppID write fAppID;
property SpaceName: String read fSpaceName write fSpaceName;
property ResourceDir: String read fResourceDir write fResourceDir;
property ExcludeMask: String read fExcludeMask write fExcludeMask;
property MainNib: String read fMainNib write fMainNib;
end;
{ TiPhoneEnvironmentOptions }
TSDKInfo = class(TObject)
devName : String;
devPath : String;
simName : String;
simPath : String;
options : String;
end;
TiPhoneEnvironmentOptions = class(TAbstractIDEEnvironmentOptions)
private
fPlatformsBaseDir : String;
fCompilerPath : String;
fBaseRTLPath : String;
fCommonOpt : String;
fSimAppsPath : String;
fSimBundle : String;
fDefaultSDK : String;
fVersions : TStringList;
protected
function XMLFileName: String;
procedure ClearVersionsInfo;
procedure FoundSDK(const Version, DevSDKName, DevSDKPath, SimSDKName, SimSDKPath: String);
function GetSDKInfo(const Version: String): TSDKInfo;
public
constructor Create;
destructor Destroy; override;
class function GetGroupCaption: String; override;
class function GetInstance: TAbstractIDEOptions; override;
function Load: Boolean;
function Save: Boolean;
function GetSDKName(const SDKVer: String; simulator: Boolean): String;
function GetSDKFullPath(const SDKVer: String; simulator: Boolean): String;
procedure GetSDKVersions(Strings: TStrings);
procedure RefreshVersions;
property PlatformsBaseDir: String read fPlatformsBaseDir write fPlatformsBaseDir;
property CompilerPath: String read fCompilerPath write fCompilerPath;
property BaseRTLPath: String read fBaseRTLPath write fBaseRTLPath;
property CommonOpt: String read fCommonOpt write fCommonOpt;
property SimBundle: String read fSimBundle write fSimBundle;
property SimAppsPath: String read fSimAppsPath write fSimAppsPath;
property DefaultSDK: String read fDefaultSDK write fDefaultSDK;
end;
function EnvOptions: TiPhoneEnvironmentOptions;
function ProjOptions: TiPhoneProjectOptions;
type
TSDKFoundEvent = procedure (const Version: String;
const DeviceSDKName, DeviceSDKPath, SimSDKName, SimSDKPath: String) of object;
function ScanForSDK(const PlatformDir: String; FoundProc: TSDKFoundEvent): Boolean;
var
iPhoneEnvGroup : Integer;
iPhonePrjGroup : Integer;
implementation
var
fEnvOptions : TiPhoneEnvironmentOptions = nil;
fProjOptions : TiPhoneProjectOptions = nil;
const
DefaultXMLName = 'iphoneextconfig.xml';
optisIphone = 'iPhone/isiPhoneApp';
optSDK = 'iPhone/SDK';
optAppID = 'iPhone/AppID';
optSpaceName = 'iPhone/SimSpaceName';
optResourceDir = 'iPhone/ResourceDir';
optExcludeMask = 'iPhone/ExcludeMask';
optMainNib = 'iPhone/MainNib';
function EnvOptions: TiPhoneEnvironmentOptions;
begin
if not Assigned(fEnvOptions) then
fEnvOptions:=TiPhoneEnvironmentOptions.Create;
Result:=fEnvOptions;
end;
function ProjOptions: TiPhoneProjectOptions;
begin
if not Assigned(fProjOptions) then
fProjOptions:=TiPhoneProjectOptions.Create;
Result:=fProjOptions;
end;
procedure InitOptions;
begin
iPhoneEnvGroup := GetFreeIDEOptionsGroupIndex(GroupEnvironment);
iPhonePrjGroup := GetFreeIDEOptionsGroupIndex(GroupProject);
RegisterIDEOptionsGroup(iPhoneEnvGroup, TiPhoneEnvironmentOptions);
RegisterIDEOptionsGroup(iPhonePrjGroup, TiPhoneProjectOptions);
end;
procedure FreeOptions;
begin
fEnvOptions.Free;
end;
{ TiPhoneEnvironmentOptions }
class function TiPhoneEnvironmentOptions.GetGroupCaption: String;
begin
Result:='iPhone Environment';
end;
class function TiPhoneEnvironmentOptions.GetInstance: TAbstractIDEOptions;
begin
Result:=EnvOptions;
end;
function TiPhoneEnvironmentOptions.XMLFileName: String;
begin
Result:=IncludeTrailingPathDelimiter(LazarusIDE.GetPrimaryConfigPath)+DefaultXMLName;
end;
procedure TiPhoneEnvironmentOptions.ClearVersionsInfo;
var
i : Integer;
begin
for i:=0 to fVersions.Count-1 do begin
fVersions.Objects[i].Free;
fVersions.Objects[i]:=nil;
end;
fVersions.Clear;
end;
procedure TiPhoneEnvironmentOptions.FoundSDK(const Version, DevSDKName,
DevSDKPath, SimSDKName, SimSDKPath: String);
var
info: TSDKInfo;
begin
info:=TSDKInfo.Create;
info.devName:=DevSDKName;
info.devPath:=DevSDKPath;
info.simName:=SimSDKName;
info.simPath:=SimSDKPath;
fVersions.AddObject(Version, info);
end;
function TiPhoneEnvironmentOptions.GetSDKInfo(const Version: String): TSDKInfo;
var
i : Integer;
begin
i:=fVersions.IndexOf(Version);
if i<0 then Result:=nil
else Result:=TSDKInfo(fVersions.Objects[i]);
end;
function GetDefaultPlatformPath: WideString;
begin
//todo:
Result:='/Developer/Platforms';
end;
function GetDefaultSimBundlePath: WideString;
begin
//todo:
Result:=IncludeTrailingPathDelimiter(GetDefaultPlatformPath)+
'iPhoneSimulator.platform/Developer/Applications/iPhone Simulator.app';
end;
function GetDefaultSimAppPath: WideSTring;
begin
//todo:
Result:=IncludeTrailingPathDelimiter(GetUserDir)+
'Library/Applications Support/iPhone Simulator/User/Applications/';
end;
constructor TiPhoneEnvironmentOptions.Create;
begin
inherited Create;
fPlatformsBaseDir := GetDefaultPlatformPath;
fSimAppsPath := GetDefaultSimAppPath;
fSimBundle := GetDefaultSimBundlePath;
fCompilerPath := '/usr/local/bin/fpc';
fVersions:=TStringList.Create;
end;
destructor TiPhoneEnvironmentOptions.Destroy;
begin
ClearVersionsInfo;
fVersions.Free;
inherited Destroy;
end;
function TiPhoneEnvironmentOptions.Load: Boolean;
var
xmlcfg : TXMLConfig;
begin
Result:=true;
try
xmlcfg := TXMLConfig.Create(nil);
try
xmlcfg.RootName:='config';
xmlcfg.Filename:=XMLFileName;
fPlatformsBaseDir := UTF8Encode(xmlcfg.GetValue('Platforms', fPlatformsBaseDir ));
fCompilerPath := UTF8Encode(xmlcfg.GetValue('Compiler', fCompilerPath));
fBaseRTLPath := UTF8Encode(xmlcfg.GetValue('RTLPath', fBaseRTLPath));
fCommonOpt := UTF8Encode(xmlcfg.GetValue('CompilerOptions', fCommonOpt));
fSimBundle := UTF8Encode(xmlcfg.GetValue('SimBundle', fSimBundle));
fSimAppsPath := UTF8Encode(xmlcfg.GetValue('SimAppPath', fSimAppsPath));
fDefaultSDK := UTF8Encode(xmlcfg.GetValue('DefaultSDK', fDefaultSDK));
RefreshVersions;
if (fDefaultSDK = '') and (fVersions.Count>0) then
fDefaultSDK:=fVersions[0];
finally
xmlcfg.Free;
end;
except
Result:=false;
end;
end;
function TiPhoneEnvironmentOptions.Save: Boolean;
var
xmlcfg : TXMLConfig;
begin
Result:=true;
try
xmlcfg := TXMLConfig.Create(nil);
try
xmlcfg.RootName:='config';
xmlcfg.Filename:=XMLFileName;
xmlcfg.SetValue('Platforms', UTF8Decode(fPlatformsBaseDir));
xmlcfg.SetValue('Compiler', UTF8Decode(fCompilerPath));
xmlcfg.SetValue('RTLPath', UTF8Decode(fBaseRTLPath));
xmlcfg.SetValue('CompilerOptions', UTF8Decode(fCommonOpt));
xmlcfg.SetValue('SimBundle', UTF8Decode(fSimBundle));
xmlcfg.SetValue('SimAppPath', UTF8Decode(fSimAppsPath));
xmlcfg.SetValue('DefaultSDK', UTF8Decode(fDefaultSDK));
finally
xmlcfg.Free;
end;
except
Result:=false;
end;
end;
function TiPhoneEnvironmentOptions.GetSDKName(const SDKVer: String; simulator: Boolean): String;
var
info : TSDKInfo;
begin
info:=GetSDKInfo(SDKVer);
if not Assigned(info) then Result:=''
else begin
if simulator then Result:=info.simName
else Result:=info.devName;
end;
end;
function TiPhoneEnvironmentOptions.GetSDKFullPath(const SDKVer: String; simulator: Boolean): String;
var
info : TSDKInfo;
begin
info:=GetSDKInfo(SDKVer);
if not Assigned(info) then Result:=''
else begin
if simulator then Result:=info.simPath
else Result:=info.devPath;
end;
end;
procedure TiPhoneEnvironmentOptions.GetSDKVersions(Strings: TStrings);
var
i : Integer;
begin
for i:=0 to fVersions.Count-1 do
Strings.Add( fVersions[i] );
end;
procedure TiPhoneEnvironmentOptions.RefreshVersions;
begin
ClearVersionsInfo;
ScanForSDK(EnvOptions.PlatformsBaseDir, @FoundSDK);
end;
{ TiPhoneProjectOptions }
procedure TiPhoneProjectOptions.Reset;
begin
fisiPhone:=false;
fSDK:='iPhone 2.0';
fAppID:='com.mycompany.myapplication';
fSpaceName:='';
DataWritten:=false;
end;
constructor TiPhoneProjectOptions.Create;
begin
inherited Create;
Reset;
end;
class function TiPhoneProjectOptions.GetGroupCaption: String;
begin
Result:='iPhone';
end;
class function TiPhoneProjectOptions.GetInstance: TAbstractIDEOptions;
begin
Result:=ProjOptions;
end;
function TiPhoneProjectOptions.Load: Boolean;
begin
Result:=True;
with LazarusIDE.ActiveProject do begin
DataWritten:=CustomData.Contains(optisIphone);
fisiPhone:=(DataWritten) and (CustomData.Values[optisIphone] = 'true');
if CustomData.Contains(optSDK) then fSDK:=CustomData.Values[optSDK];
if CustomData.Contains(optAppID) then fAppID:=CustomData.Values[optAppID];
fSpaceName:=CustomData.Values[optSpaceName];
if fSpaceName='' then fSpaceName:=RandomSpaceName;
if CustomData.Contains(optResourceDir) then fResourceDir:=CustomData.Values[optResourceDir];
if CustomData.Contains(optExcludeMask) then fExcludeMask:=CustomData.Values[optExcludeMask];
if CustomData.Contains(optMainNib) then fMainNib:=CustomData.Values[optMainNib];
end;
end;
function TiPhoneProjectOptions.Save: Boolean;
const
BoolStr : array[Boolean] of String = ('false', 'true');
begin
Result:=True;
{do not write iPhone related info to non-iPhone projects}
if DataWritten or fisiPhone then
with LazarusIDE.ActiveProject do begin
CustomData.Values[optisIPhone] := BoolStr[fisiPhone];
CustomData.Values[optSDK]:=fSDK;
CustomData.Values[optAppID]:=fAppID;
CustomData.Values[optSpaceName]:=fSpaceName;
CustomData.Values[optResourceDir]:=fResourceDir;
CustomData.Values[optExcludeMask]:=fExcludeMask;
CustomData.Values[optMainNib]:=fMainNib;
end;
end;
type
TSDKDescription = record
FullPath : String; {full SDK path}
Name : String;
Alternate : String; {alternate SDK -> iphonesimulator for iphoneos}
Version : String;
isSim : Boolean; {true for real iPhoneOS, false for iPhoneSimulator}
end;
// todo: implement reading .plist via OSX functions! (in case a .plist format changes)
function ReadSDKSettings(const FileName: String; var Descr: TSDKDescription): Boolean;
var
plist : TPListFile;
begin
Result:=False;
plist:=TPListFile.Create(FileName);
Descr.Name:=plist.GetStrValue('CanonicalName');
Descr.Alternate:=plist.GetStrValue('AlternateSDK');
Descr.Version:=plist.GetStrValue('Version');
plist.Free;
end;
function isSDKDir(const SDKDir: String; var d: TSDKDescription): Boolean;
var
plist : String;
begin
plist := IncludeTrailingPathDelimiter(SDKDir)+'SDKSettings.plist';
Result:=FileExists(plist);
if not Result then Exit;
ReadSDKSettings(plist, d);
d.FullPath:=SDKDir;
end;
function ScanForSDK(const PlatformDir: String; FoundProc: TSDKFoundEvent): Boolean;
const
PlatformName: array [Boolean] of String = ('iPhoneOS.platform','iPhoneSimulator.platform');
SDKSubDir = PathDelim+'Developer'+PathDelim+'SDKs'+PathDelim;
var
isSim : Boolean;
dir : String;
sr : TSearchRec;
sdks : array of TSDKDescription;
descr : TSDKDescription;
cnt : Integer;
simname : String;
simpath : String;
i,j : Integer;
procedure AddDescription(const d: TSDKDescription);
begin
if cnt = length(sdks) then begin
if cnt = 0 then SetLength(sdks, 16)
else SetLength(sdks, cnt*2);
end;
sdks[cnt]:=d;
inc(cnt);
end;
begin
Result:=Assigned(FoundProc);
if not Result then Exit;
cnt:=0;
for isSim:=false to true do begin
dir := IncludeTrailingPathDelimiter(PlatformDir) + PlatformName[isSim] + SDKSubDir;
if FindFirst(dir+'*', faAnyFile, sr)=0 then begin
repeat
if (sr.Attr and faDirectory>0) and (ExtractFileExt(sr.Name) = '.sdk') then
if isSDKDir( dir + sr.Name, descr) then begin
descr.isSim:=isSim;
AddDescription(descr);
end;
until FindNext(sr)<>0;
FindClose(sr);
end;
end;
for i:=0 to cnt-1 do
if not sdks[i].isSim then begin
simname:='';
simpath:='';
for j:=0 to cnt-1 do
if (sdks[j].isSim) and (sdks[i].Alternate=sdks[j].Name) then begin
simname:=sdks[j].Name;
simpath:=sdks[j].FullPath;
end;
FoundProc(sdks[i].Version, sdks[i].Name, sdks[i].FullPath, simname, simpath);
end;
Result:=True;
end;
initialization
InitOptions;
finalization
FreeOptions;
end.