iphonelazext: implemented creating/deleting xib files from inside of project options

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1214 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
skalogryz
2010-05-02 22:57:55 +00:00
parent 7a69f33b79
commit 058d550ef9
11 changed files with 652 additions and 164 deletions

View File

@ -50,7 +50,7 @@ type
public
//isiPhoneMenu :TIDEMenuCommand;
constructor Create;
procedure UpdateXCode(Sender: TObject);
procedure UpdateXcode(Sender: TObject);
procedure SimRun(Sender: TObject);
//procedure isProjectClicked(Sender: TObject);
end;
@ -339,7 +339,7 @@ begin
//isiPhoneMenu.Checked:=ProjOptions.isIPhoneApp;
end;
procedure TiPhoneExtension.UpdateXCode(Sender: TObject);
procedure TiPhoneExtension.UpdateXcode(Sender: TObject);
var
templates : TStringList;
build : TStringList;

View File

@ -20,7 +20,8 @@ unit iPhoneExtOptions;
interface
uses
Classes, SysUtils, IDEOptionsIntf, LazIDEIntf, ProjectIntf, iPhoneBundle, DOM, XMLRead, XMLConf, PlistFile;
Classes, SysUtils, IDEOptionsIntf, LazIDEIntf, ProjectIntf,
iPhoneBundle, DOM, XMLRead, XMLConf, XcodeUtils;
const
DefaultResourceDir = 'Resources';
@ -112,12 +113,6 @@ 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;
@ -409,101 +404,6 @@ begin
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;

View File

@ -18,7 +18,7 @@
<Description Value="iPhone Development Lazarus extension"/>
<License Value="LGPL"/>
<Version Minor="6"/>
<Files Count="11">
<Files Count="13">
<Item1>
<Filename Value="ideext.pas"/>
<HasRegisterProc Value="True"/>
@ -64,6 +64,14 @@
<Filename Value="lazfilesutils.pas"/>
<UnitName Value="lazfilesutils"/>
</Item11>
<Item12>
<Filename Value="xcodeutils.pas"/>
<UnitName Value="xcodeutils"/>
</Item12>
<Item13>
<Filename Value="newxibdialog.pas"/>
<UnitName Value="newxibdialog"/>
</Item13>
</Files>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="3">

View File

@ -1,4 +1,4 @@
{ This file was automatically created by Lazarus. do not edit!
{ This file was automatically created by Lazarus. Do not edit!
This source is only used to compile and install the package.
}
@ -9,7 +9,7 @@ interface
uses
ideext, iPhoneExtStr, iPhoneBundle, XCodeProject,
environment_iphone_options, project_iphone_options, iPhoneExtOptions,
xcodetemplate, lazfilesutils, LazarusPackageIntf;
xcodetemplate, LazFilesUtils, XcodeUtils, newXibDialog, LazarusPackageIntf;
implementation

View File

@ -12,7 +12,7 @@
* *
*****************************************************************************
}
unit lazfilesutils;
unit LazFilesUtils;
{$mode objfpc}{$H+}
@ -21,8 +21,7 @@ interface
uses
{$ifdef Unix}BaseUnix,{$endif}
Classes, SysUtils, FileUtil, Masks,
LazIDEIntf,ProjectIntf;
LazIDEIntf, ProjectIntf, process;
function ResolveProjectPath(const path: string; project: TLazProject = nil): string;
@ -33,6 +32,10 @@ function NeedQuotes(const path: string): Boolean;
function CopySymLinks(const SrcDir, DstDir, FilterMask: string): Boolean;
procedure EnumFilesAtDir(const PathUtf8 : AnsiString; Dst: TStrings);
procedure EnumFilesAtDir(const PathUtf8, AMask : AnsiString; Dst: TStrings);
procedure ExecCmdLineNoWait(const CmdLineUtf8: AnsiString);
implementation
{$ifdef Unix}
@ -177,5 +180,47 @@ begin
end;
end;
procedure EnumFilesAtDir(const PathUtf8, AMask : AnsiString; Dst: TStrings);
var
mask : TMask;
sr : TSearchRec;
path : AnsiString;
begin
if (AMask='') or (trim(AMask)='*') then mask:=nil else mask:=TMask.Create(AMask);
try
path:=IncludeTrailingPathDelimiter(PathUtf8);
if FindFirstUTF8(path+AllFilesMask, faAnyFile, sr) = 0 then begin
repeat
if (sr.Name<>'.') and (sr.Name<>'..') then
if not Assigned(mask) or mask.Matches(sr.Name) then
Dst.Add(path+sr.Name);
until FindNextUTF8(sr)<>0;
FindCloseUTF8(sr);
end;
finally
mask.Free;
end;
end;
procedure EnumFilesAtDir(const PathUtf8 : AnsiString; Dst: TStrings);
begin
EnumFilesAtDir(PathUTF8, AllFilesMask, Dst);
end;
procedure ExecCmdLineNoWait(const CmdLineUtf8: AnsiString);
var
proc : TProcess;
begin
proc:=TProcess.Create(nil);
try
proc.CommandLine:=CmdLineUtf8;
//proc.WaitOnExit:=WaitExit;
proc.Execute;
finally
proc.Free;
end;
end;
end.

View File

@ -0,0 +1,81 @@
object newXibForm: TnewXibForm
Left = 583
Height = 447
Top = 195
Width = 477
BorderIcons = [biSystemMenu]
BorderStyle = bsDialog
Caption = 'Choose a template'
ClientHeight = 447
ClientWidth = 477
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '0.9.29'
object Edit1: TEdit
Left = 94
Height = 22
Top = 24
Width = 370
OnKeyPress = Edit1KeyPress
TabOrder = 0
Text = 'Edit1'
end
object Label1: TLabel
Left = 16
Height = 18
Top = 24
Width = 61
Caption = 'FileName:'
ParentColor = False
end
object DrawGrid1: TDrawGrid
Left = 16
Height = 200
Top = 64
Width = 448
ColCount = 1
DefaultColWidth = 80
DefaultDrawing = False
DefaultRowHeight = 96
ExtendedSelect = False
FixedCols = 0
FixedRows = 0
GridLineWidth = 0
Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goSmoothScroll]
ScrollBars = ssVertical
TabOrder = 1
OnDrawCell = DrawGrid1DrawCell
OnSelection = DrawGrid1Selection
OnSelectCell = DrawGrid1SelectCell
end
object Button1: TButton
Left = 160
Height = 20
Top = 400
Width = 70
AutoSize = True
Caption = 'Cancel'
ModalResult = 2
TabOrder = 2
end
object Button2: TButton
Left = 248
Height = 20
Top = 400
Width = 71
AutoSize = True
Caption = 'Choose'
ModalResult = 1
OnClick = Button2Click
TabOrder = 3
end
object Memo1: TMemo
Left = 16
Height = 112
Top = 272
Width = 448
ReadOnly = True
ScrollBars = ssAutoVertical
TabOrder = 4
end
end

View File

@ -0,0 +1,228 @@
unit newXibDialog;
{$mode objfpc}{$H+}
interface
uses
MacOSAll,
Types,Classes,SysUtils,FileUtil,LResources,Forms,Controls,Graphics,Dialogs,StdCtrls,LCLProc,
Grids,
//todo: use LCL file loading and drawing, instead of OSX
CarbonGDIObjects, CarbonProc;
type
{ TnewXibForm }
TnewXibForm = class(TForm)
Button1:TButton;
Button2:TButton;
DrawGrid1:TDrawGrid;
Edit1:TEdit;
Label1:TLabel;
Memo1:TMemo;
procedure Button2Click(Sender:TObject);
procedure DrawGrid1DrawCell(Sender:TObject;aCol,aRow:Integer;aRect:TRect;
aState:TGridDrawState);
procedure DrawGrid1SelectCell(Sender:TObject;aCol,aRow:Integer;var CanSelect
:Boolean);
procedure DrawGrid1Selection(Sender:TObject;aCol,aRow:Integer);
procedure Edit1KeyPress(Sender:TObject;var Key:char);
procedure FormCreate(Sender:TObject);
procedure FormDestroy(Sender:TObject);
private
{ private declarations }
SelectedXib : String;
Items : TList;
CustomName : Boolean;
public
{ public declarations }
procedure AddTemplate(const AName, SourceXibFile, ADescr, IconFile: AnsiString);
function Execute(var FileName, SourceXibFile: AnsiString): Boolean;
end;
var
newXibForm: TnewXibForm;
implementation
{$R *.lfm}
type
{ TXibItem }
TXibItem = class(TObject)
image : TBitmap;
sourcefile : AnsiString;
descr : AnsiString;
name : AnsiString;
constructor Create(const AName, ASourceFile, ADescr, IconFileName: AnsiString);
destructor Destroy; override;
end;
{ TXibItem }
constructor TXibItem.Create(const AName,ASourceFile,ADescr, IconFileName:AnsiString);
var
url : CFURLRef;
data : CGImageSourceRef;
cf : CFStringRef;
img : CGImageRef;
ctx : CGContextRef;
space : CGColorSpaceRef;
r : CGRect;
w : WideString;
begin
inherited Create;
w:=UTF8Decode(AName);
if w<>'' then w[1]:=WideUpperCase(w[1])[1];
name:=UTF8Encode(w);
sourcefile:=ASourceFile;
descr:=ADescr;
if IconFileName<>'' then begin
CreateCFString(IconFileName, cf);
url:=CFURLCreateWithFileSystemPathRelativeToBase(kCFAllocatorDefault , cf,
kCFURLPOSIXPathStyle, false, nil);
data:=CGImageSourceCreateWithURL(url, nil);
img:=CGImageSourceCreateImageAtIndex(data, 0, nil);
image:=TBitmap.Create;
image.PixelFormat:=pf32bit;
image.SetSize( 64, 64);
image.BeginUpdate;
space:=CGColorSpaceCreateDeviceRGB;
ctx:=CGBitmapContextCreate(image.RawImage.Data, image.Width, image.Height, 8,
image.Width*4, space, kCGImageAlphaPremultipliedFirst);
r.origin.x:=0; r.origin.y:=0;
r.size.width:=image.Width; r.size.height:=image.Height;
CGColorSpaceRelease(space);
CGContextDrawImage(ctx, r, img);
CGContextRelease(ctx);
image.EndUpdate;
CFRelease(img);
CFRelease(data);
CFRelease(url);
end;
end;
destructor TXibItem.Destroy;
begin
image.Free;
inherited Destroy;
end;
{ TnewXibForm }
procedure TnewXibForm.FormCreate(Sender:TObject);
begin
Items:=TList.Create;
end;
procedure TnewXibForm.DrawGrid1DrawCell(Sender:TObject;aCol,aRow:Integer;aRect:
TRect;aState:TGridDrawState);
var
info : TXibItem;
sz : TSize;
x,y : Integer;
idx : integer;
begin
idx:=DrawGrid1.ColCount*aRow+aCol;
if (idx>=0) and (idx<Items.Count) then
info:=TXibItem(Items[idx])
else
info:=nil;
if not Assigned(info) then Exit;
if gdSelected in aState then begin
DrawGrid1.Canvas.Brush.Color:=clHighlight;
DrawGrid1.Canvas.Font.Color:=clHighlightText;
end else begin
DrawGrid1.Canvas.Brush.Color:=clWindow;
DrawGrid1.Canvas.Font.Color:=clWindowText;
end;
DrawGrid1.Canvas.FillRect(aRect);
if Assigned(info.image) then
DrawGrid1.Canvas.Draw(aRect.Left+4, aRect.Top, info.image);
sz:=DrawGrid1.Canvas.TextExtent(info.name);
x:=aRect.Left+ ((aRect.Right-aRect.Left) - sz.cx) div 2;
y:=aRect.Top + info.image.Height+4;
DrawGrid1.Canvas.TextOut(x, y, info.name);
end;
procedure TnewXibForm.Button2Click(Sender:TObject);
begin
end;
procedure TnewXibForm.DrawGrid1SelectCell(Sender:TObject;aCol,aRow:Integer;var
CanSelect:Boolean);
var
idx : integer;
begin
idx:=DrawGrid1.ColCount*aRow+aCol;
CanSelect:=(idx>=0) and (idx<Items.Count);
if CanSelect then begin
Memo1.Text:=TXibItem(Items[idx]).descr;
if not CustomName then
Edit1.Text:=TXibItem(Items[idx]).name;
SelectedXib:=TXibItem(Items[idx]).sourcefile;
end else begin
Memo1.Text:='';
SelectedXib:='';
end;
Button2.Enabled:=CanSelect;
end;
procedure TnewXibForm.DrawGrid1Selection(Sender:TObject;aCol,aRow:Integer);
begin
end;
procedure TnewXibForm.Edit1KeyPress(Sender:TObject;var Key:char);
begin
CustomName:=True;
end;
procedure TnewXibForm.FormDestroy(Sender:TObject);
var
i : Integer;
begin
for i:=0 to Items.Count-1 do TObject(Items[i]).Free;
end;
procedure TnewXibForm.AddTemplate(const AName,SourceXibFile,ADescr, IconFile:AnsiString);
begin
Items.Add( TXibItem.Create(AName, SourceXibFile, ADescr, IconFile));
end;
function TnewXibForm.Execute(var FileName,SourceXibFile:AnsiString):Boolean;
var
w : integer;
begin
if Items.Count=0 then begin
Result:=False;
Exit;
end;
w:=DrawGrid1.ClientWidth div DrawGrid1.DefaultColWidth;
if w=0 then w:=1;
DrawGrid1.ColCount:=w;
DrawGrid1.RowCount:=Items.Count div w;
CustomName:=False;
Result:=ShowModal = mrOK;
if Result then begin
FileName:=Edit1.Text;
SourceXibFile:=SelectedXib;
end;
end;
end.

View File

@ -4,8 +4,8 @@ inherited iPhoneProjectOptionsEditor: TiPhoneProjectOptionsEditor
ClientHeight = 474
ClientWidth = 620
OnClick = FrameClick
DesignLeft = 611
DesignTop = 128
DesignLeft = 463
DesignTop = 306
object chkisPhone: TCheckBox[0]
Left = 16
Height = 18
@ -154,7 +154,31 @@ inherited iPhoneProjectOptionsEditor: TiPhoneProjectOptionsEditor
OnClick = btnShowInFinderClick
TabOrder = 6
end
object nibsPopup: TPopupMenu[15]
object btnAddXib: TButton[15]
AnchorSideLeft.Control = btnRemoveXib
AnchorSideRight.Control = btnRemoveXib
AnchorSideRight.Side = asrBottom
Left = 40
Height = 20
Top = 283
Width = 74
Anchors = [akTop, akLeft, akRight]
AutoSize = True
Caption = 'Add'
OnClick = btnAddXibClick
TabOrder = 7
end
object btnRemoveXib: TButton[16]
Left = 40
Height = 20
Top = 312
Width = 74
AutoSize = True
Caption = 'Remove'
OnClick = btnRemoveXibClick
TabOrder = 8
end
object nibsPopup: TPopupMenu[17]
OnPopup = nibsPopupPopup
left = 256
top = 288

View File

@ -3,7 +3,7 @@
LazarusResources.Add('TiPhoneProjectOptionsEditor','FORMDATA',[
'TPF0'#241#27'TiPhoneProjectOptionsEditor'#26'iPhoneProjectOptionsEditor'#6'H'
+'eight'#3#218#1#5'Width'#3'l'#2#12'ClientHeight'#3#218#1#11'ClientWidth'#3'l'
+#2#7'OnClick'#7#10'FrameClick'#10'DesignLeft'#3'c'#2#9'DesignTop'#3#128#0#0
+#2#7'OnClick'#7#10'FrameClick'#10'DesignLeft'#3#207#1#9'DesignTop'#3'2'#1#0
+#242#2#0#9'TCheckBox'#10'chkisPhone'#4'Left'#2#16#6'Height'#2#18#3'Top'#2#16
+#5'Width'#3#199#0#7'Caption'#6#29'is iPhone application project'#8'OnChange'
+#7#16'chkisPhoneChange'#8'TabOrder'#2#0#0#0#242#2#1#6'TLabel'#8'lblAppID'#4
@ -46,8 +46,15 @@ LazarusResources.Add('TiPhoneProjectOptionsEditor','FORMDATA',[
+'t'#2#246#11'ParentColor'#8#10'ParentFont'#8#0#0#242#2#14#7'TButton'#15'btnS'
+'howInFinder'#4'Left'#3#229#1#6'Height'#2#20#3'Top'#3#176#0#5'Width'#2'u'#7
+'Anchors'#11#5'akTop'#7'akRight'#0#8'AutoSize'#9#7'Caption'#6#14'Show in Fin'
+'der'#7'OnClick'#7#20'btnShowInFinderClick'#8'TabOrder'#2#6#0#0#242#2#15#10
+'TPopupMenu'#9'nibsPopup'#7'OnPopup'#7#14'nibsPopupPopup'#4'left'#3#0#1#3'to'
+'p'#3' '#1#0#9'TMenuItem'#9'mnuOpenIB'#7'Caption'#6#22'Open Interface Builde'
+'r'#7'OnClick'#7#14'mnuOpenIBClick'#0#0#0#0
+'der'#7'OnClick'#7#20'btnShowInFinderClick'#8'TabOrder'#2#6#0#0#242#2#15#7'T'
+'Button'#9'btnAddXib'#22'AnchorSideLeft.Control'#7#12'btnRemoveXib'#23'Ancho'
+'rSideRight.Control'#7#12'btnRemoveXib'#20'AnchorSideRight.Side'#7#9'asrBott'
+'om'#4'Left'#2'('#6'Height'#2#20#3'Top'#3#27#1#5'Width'#2'J'#7'Anchors'#11#5
+'akTop'#6'akLeft'#7'akRight'#0#8'AutoSize'#9#7'Caption'#6#3'Add'#7'OnClick'#7
+#14'btnAddXibClick'#8'TabOrder'#2#7#0#0#242#2#16#7'TButton'#12'btnRemoveXib'
+#4'Left'#2'('#6'Height'#2#20#3'Top'#3'8'#1#5'Width'#2'J'#8'AutoSize'#9#7'Cap'
+'tion'#6#6'Remove'#7'OnClick'#7#17'btnRemoveXibClick'#8'TabOrder'#2#8#0#0#242
+#2#17#10'TPopupMenu'#9'nibsPopup'#7'OnPopup'#7#14'nibsPopupPopup'#4'left'#3#0
+#1#3'top'#3' '#1#0#9'TMenuItem'#9'mnuOpenIB'#7'Caption'#6#22'Open Interface '
+'Builder'#7'OnClick'#7#14'mnuOpenIBClick'#0#0#0#0
]);

View File

@ -19,9 +19,9 @@ unit project_iphone_options;
interface
uses
Classes,SysUtils,FileUtil,LResources,Forms,StdCtrls,Masks,CheckLst,Buttons,
Classes,SysUtils,FileUtil,LResources,Forms,StdCtrls,CheckLst,Buttons, Dialogs,
Menus,IDEOptionsIntf,ProjectIntf,LazIDEIntf,iPhoneExtStr,
iPhoneExtOptions, process, Controls;
iPhoneExtOptions, Controls, LazFilesUtils, XcodeUtils, newXibDialog;
type
@ -29,6 +29,8 @@ type
TiPhoneProjectOptionsEditor = class(TAbstractIDEOptionsEditor)
btnShowInFinder:TButton;
btnAddXib:TButton;
btnRemoveXib:TButton;
Label5:TLabel;
mnuOpenIB:TMenuItem;
nibFilesBox:TCheckListBox;
@ -45,7 +47,10 @@ type
lblAppIDHint: TLabel;
lblSDKVer: TLabel;
nibsPopup:TPopupMenu;
procedure btnAddXibClick(Sender:TObject);
procedure btnRemoveXibClick(Sender:TObject);
procedure btnShowInFinderClick(Sender:TObject);
procedure Button1Click(Sender:TObject);
procedure chkisPhoneChange(Sender:TObject);
procedure cmbSDKsChange(Sender: TObject);
procedure edtExcludeChange(Sender: TObject);
@ -81,47 +86,8 @@ type
property OnChanged: TNotifyEvent read fOnChanged write fOnChanged;
end;
procedure EnumFilesAtDir(const PathUtf8, AMask : AnsiString; Dst: TStrings);
procedure ExecCmdLineNoWait(const CmdLineUtf8: AnsiString);
implementation
procedure EnumFilesAtDir(const PathUtf8, AMask : AnsiString; Dst: TStrings);
var
mask : TMask;
sr : TSearchRec;
path : AnsiString;
begin
if (AMask='') or (trim(AMask)='*') then mask:=nil else mask:=TMask.Create(AMask);
try
path:=IncludeTrailingPathDelimiter(PathUtf8);
if FindFirstUTF8(path+AllFilesMask, faAnyFile, sr) = 0 then begin
repeat
if (sr.Name<>'.') and (sr.Name<>'..') then
if not Assigned(mask) or mask.Matches(sr.Name) then
Dst.Add(path+sr.Name);
until FindNextUTF8(sr)<>0;
FindCloseUTF8(sr);
end;
finally
mask.Free;
end;
end;
procedure ExecCmdLineNoWait(const CmdLineUtf8: AnsiString);
var
proc : TProcess;
begin
proc:=TProcess.Create(nil);
try
proc.CommandLine:=CmdLineUtf8;
//proc.WaitOnExit:=WaitExit;
proc.Execute;
finally
proc.Free;
end;
end;
{ TiPhoneProjectOptionsEditor }
procedure TiPhoneProjectOptionsEditor.cmbSDKsChange(Sender: TObject);
@ -148,6 +114,49 @@ begin
if DirectoryExistsUTF8(path) then ExecCmdLineNoWait('open "'+path +'"');
end;
procedure TiPhoneProjectOptionsEditor.btnAddXibClick(Sender:TObject);
var
FileName : AnsiString;
SrcXib : AnsiString;
ResDir : AnsiString;
begin
newXibForm:=TnewXibForm.Create(Self);
ScanForXibTemplates(
XibTemplateDir( IncludeTrailingPathDelimiter(EnvOptions.PlatformsBaseDir)+iPhoneOSplatform),
@newXibForm.AddTemplate);
if (newXibForm.Execute(FileName, SrcXib)) and (SrcXib<>'')then begin
ResDir:=edtResDir.Text;
LazarusIDE.ActiveProject.LongenFilename(ResDir);
ForceDirectoriesUTF8(ResDir);
if not CopyFile(SrcXib, ChangeFileExt(IncludeTrailingPathDelimiter(ResDir)+FileName,'.xib')) then
ShowMessage('Failed to create Nib file');
RefreshXIBList;
end;
newXibForm.Free;
newXibForm:=nil;
end;
procedure TiPhoneProjectOptionsEditor.btnRemoveXibClick(Sender:TObject);
var
XibName : AnsiString;
begin
if nibFilesBox.ItemIndex<0 then Exit;
XibName:=edtResDir.Text;
LazarusIDE.ActiveProject.LongenFilename(XibName);
XibName:=ChangeFileExt(IncludeTrailingPathDelimiter(XibName)+nibFilesBox.Items[nibFilesBox.ItemIndex],'.xib');
if FileExistsUTF8(XibName) then DeleteFileUTF8(XibName);
RefreshXIBList;
end;
procedure TiPhoneProjectOptionsEditor.Button1Click(Sender:TObject);
begin
end;
procedure TiPhoneProjectOptionsEditor.chkisPhoneChange(Sender:TObject);
begin
SetControlsEnabled(chkisPhone.Checked);

View File

@ -0,0 +1,186 @@
unit XcodeUtils;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, PlistFile, LazFilesUtils;
const
iPhoneOSplatform = 'iPhoneOS.platform';
// file names should utf8 encoded
// Scanning Xcode platform for available SDKs
type
TSDKFoundEvent = procedure (const Version: String;
const DeviceSDKName, DeviceSDKPath, SimSDKName, SimSDKPath: String) of object;
function ScanForSDK(const PlatformDir: String; FoundProc: TSDKFoundEvent): Boolean;
// Scanning for Templates
function XibTemplateDir(const PlatformDir: AnsiString): AnsiString;
type
TScanTemplateProc = procedure ( const TemplateName, XibFileName,
Description, IconFileName: AnsiString) of object;
procedure ScanForXibTemplates(const TemplateDir: AnsiString; Callback: TScanTemplateProc);
implementation
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;
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;
function XibTemplateDir(const PlatformDir: AnsiString): AnsiString;
const
TemplatePath = 'Developer/Library/Xcode/File Templates/User Interface';
begin
Result:=IncludeTrailingPathDelimiter(PlatformDir)+TemplatePath;
end;
procedure ScanForXibTemplates(const TemplateDir: AnsiString; Callback: TScanTemplateProc);
var
dirs : TStringList;
files : TStringList;
i,j : Integer;
plist : TPListFile;
xib : AnsiString;
name : AnsiString;
descr : AnsiString;
const
XibTemplateMask = '*.pbfiletemplate';
IconFile = 'TemplateIcon.tiff';
begin
if not Assigned(Callback) or not DirectoryExists(TemplateDir) then Exit;
dirs:=TStringList.Create;
files:=TStringList.Create;
try
EnumFilesAtDir( TemplateDir, XibTemplateMask, dirs );
for i:=0 to dirs.Count-1 do begin
if DirectoryExists(dirs[i]) then begin
files.Clear;
EnumFilesAtDir(dirs[i], files);
xib:='';
for j:=0 to files.Count-1 do
if AnsiLowerCase(ExtractFileExt(files[j]))='.plist' then begin
plist:=TPListFile.Create(files[j]);
xib:=plist.GetStrValue('MainTemplateFile');
descr:=plist.GetStrValue('Description');
name:=ChangeFileExt(xib, '');
Break;
end;
if xib<>'' then begin
xib:=IncludeTrailingPathDelimiter(dirs[i])+xib;
Callback(name, xib, descr, IncludeTrailingPathDelimiter(dirs[i])+IconFile);
end;
end;
end;
finally
dirs.Free;
files.Free;
end;
end;
end.