diff --git a/components/iosdesigner/MainWindow_iPhone.template b/components/iosdesigner/MainWindow_iPhone.template new file mode 100644 index 000000000..6f9a4d4b2 --- /dev/null +++ b/components/iosdesigner/MainWindow_iPhone.template @@ -0,0 +1,100 @@ + + + + 1280 + 11D50 + 2182 + 1138.32 + 568.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 1181 + + + YES + IBUIWindow + IBUICustomObject + IBUIButton + IBProxyObject + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + PluginDependencyRecalculationVersion + + + + YES + [{Objects}] + + + + YES + [{ConnectionRecords}] + + + + YES + + 0 + + YES + + + + + [{ObjectRecords}] + + + [{flattenedProperties}] + + YES + + + + + + YES + + + + + 1000 + + + + YES + + AppDelegate + NSObject + + window + UIWindow + + + window + + window + UIWindow + + + + IBProjectSource + ./Classes/AppDelegate.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + 3 + 1181 + + diff --git a/components/iosdesigner/README.txt b/components/iosdesigner/README.txt new file mode 100644 index 000000000..8170d86d9 --- /dev/null +++ b/components/iosdesigner/README.txt @@ -0,0 +1,2 @@ +This package contains a designer to create NIB-files which can be integrated +into an iOS application. diff --git a/components/iosdesigner/ios_views.pas b/components/iosdesigner/ios_views.pas new file mode 100644 index 000000000..b71d1108d --- /dev/null +++ b/components/iosdesigner/ios_views.pas @@ -0,0 +1,1697 @@ +{ Fake components to mimic iOS's views in the Lazarus designer + + Copyright (C) 2012 Joost van der Sluis/CNOC joost@cnoc.nl + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version with the following modification: + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules,and + to copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the terms + and conditions of the license of that module. An independent module is a + module which is not derived from or based on this library. If you modify + this library, you may extend this exception to your version of the library, + but you are not obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + + 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. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +} +// The name of this unit has to be of the same length as the name of the +// iPhoneAll unit. +unit iOS_Views; + +{$mode objfpc}{$H+} +{$modeswitch ObjectiveC1} + +interface + +uses + Classes, SysUtils, Math, types, DOM, XMLWrite, Graphics; + +type + IMyWidgetDesigner = interface(IUnknown) + procedure InvalidateRect(Sender: TObject; ARect: TRect; Erase: boolean); + function CreateComponent(ParentComp: TComponent; + TypeClass: TComponentClass; + const AUnitName: shortstring; + X,Y,W,H: Integer; + DisableAutoSize: boolean): TComponent; + end; + + TiOSFakeFontType = (ftNotSet, ftSystem, ftSystemBold, ftSystemItalic); + + { TiOSFakeFontDescription } + + TiOSFakeFontDescription = class(TPersistent) + private + FFontType: TiOSFakeFontType; + FpointSize: double; + public + constructor Create; + published + property FontType: TiOSFakeFontType read FFontType write FFontType; + property pointSize: double read FpointSize write FpointSize; + end; + + { tiOSFakeComponent } + + tiOSWriteDomMethod = function (AnObjectDomElement: TDOMElement): TDOMElement of object; + + tiOSFakeComponent = class(TComponent) + private + FAcceptChildsAtDesignTime: boolean; + FChilds: TFPList; // list of tiOSFakeComponent + FHeight: integer; + FLeft: integer; + FObjectID: integer; + FParent: tiOSFakeComponent; + FTop: integer; + FWidth: integer; + // iOS + FRef: integer; + function ElementToString(AWriteDomMethod: tiOSWriteDomMethod): string; + protected + procedure SetParentComponent(Value: TComponent); override; + procedure SetParent(const AValue: tiOSFakeComponent); + function HasParent: Boolean; override; + function GetParentComponent: TComponent; override; + procedure SetHeight(const AValue: integer); + procedure SetLeft(const AValue: integer); + procedure SetTop(const AValue: integer); + procedure SetWidth(const AValue: integer); + function GetChilds(Index: integer): tiOSFakeComponent; + procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override; + procedure InternalInvalidateRect(ARect: TRect; Erase: boolean); virtual; + // iOS + procedure AddConnectionRecord(AnObjectDomElement: TDOMElement; AConnectionType, ALabel, AEventType: string); + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); virtual; + function WriteToObject(AnObjectDomElement: TDOMElement): TDOMElement; virtual; + function WriteToConnectionRecords(AnObjectDomElement: TDOMElement): TDOMElement; virtual; + function WriteToObjectRecord(AnObjectDomElement: TDOMElement): TDOMElement; virtual; + class function GetIBClassName: string; virtual; + function GetDesigner: IMyWidgetDesigner; virtual; + function GetHeight: integer; virtual; + function GetLeft: integer; virtual; + function GetTop: integer; virtual; + function GetWidth: integer; virtual; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure InitializeDefaultChildren; virtual; + procedure paint(ACanvas: TCanvas); virtual; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); virtual; + procedure InvalidateRect(ARect: TRect; Erase: boolean); + procedure Invalidate; + function ChildCount: integer; + property Parent: tiOSFakeComponent read FParent write SetParent; + property Children[Index: integer]: tiOSFakeComponent read GetChilds; + property AcceptChildsAtDesignTime: boolean read FAcceptChildsAtDesignTime; + // iOS + function getAsXIBObject: string; virtual; + function getConnectionRecords: string; virtual; + function getObjectRecord: string; virtual; + property Ref: integer read FRef write FRef; + property ObjectID: integer read FObjectID; + // Dom utils + function AddElement(ADomNode: TDOMElement; AName: string): TDOMElement; + function AddIBInt(ADomNode: TDOMElement; APropName: string; APropValue: integer; ADefaultValue: integer = MaxInt): TDOMElement; + function AddIBDouble(ADomNode: TDOMElement; APropName: string; APropValue: double): TDOMElement; + function AddIBFloat(ADomNode: TDOMElement; APropName: string; APropValue: double; ADefaultValue: double = MaxFloat): TDOMElement; + function AddIBString(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; + function AddIBReference(ADomNode: TDOMElement; APropName: string; APropValue: tiOSFakeComponent; ForceValue: boolean = false): TDOMElement; + function AddIBReference(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; + function AddIBBoolean(ADomNode: TDOMElement; APropName: string; APropValue: Boolean): TDOMElement; + function AddIBBoolean(ADomNode: TDOMElement; APropName: string; APropValue: Boolean; ADefaultValue: boolean): TDOMElement; + function AddIBBytes(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; + function AddIBObject(ADomNode: TDOMElement; APropName: string; AClass: string): TDOMElement; + function AddIBObject(ADomDocument: TXMLDocument; APropName: string; AClass: string): TDOMElement; + function AddIBColor(ADomNode: TDOMElement; APropName: string; AColor: TColor): TDOMElement; + function AddIBFontDescription(ADomNode: TDOMElement; APropName: string; AFontDescription: TiOSFakeFontDescription): TDOMElement; + published + property Left: integer read GetLeft write SetLeft; + property Top: integer read GetTop write SetTop; + property Width: integer read GetWidth write SetWidth; + property Height: integer read GetHeight write SetHeight; + end; + + { UIView } + + UIView = class(tiOSFakeComponent) + private + FCaption: string; + FNSNextResponder: UIView; + FOpaque: boolean; + FAlpha: double; + FBackgroundColor: TColor; + FHidden: boolean; + function GetNSSuperview: UIView; + procedure SetCaption(const AValue: string); + protected + procedure SetName(const NewName: TComponentName); override; + // Dom + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + procedure paint(ACanvas: TCanvas); override; + class function GetIBClassName: string; override; + property NSSuperview: UIView read GetNSSuperview; + property NSNextResponder: UIView read FNSNextResponder write FNSNextResponder; + published + property Caption: string read FCaption write SetCaption; + property Opaque: boolean read FOpaque write FOpaque; + property BackgroundColor: TColor read FBackgroundColor write FBackgroundColor; + property Alpha: double read FAlpha write FAlpha; + property Hidden: boolean read FHidden write FHidden; + end; + TUIViewClass = class of UIView; + + { NSObject } + + NSObject = class(tiOSFakeComponent) + private + FDesigner: IMyWidgetDesigner; + FFilesOwnerClass: string; + FHiddenObjectOutletName: string; + FIsHiddenObject: boolean; + procedure GetXIBSaveParam(Sender: TObject; const ParamName: String; out AValue: String); + function IsNIBRoot: boolean; + function GetFilesOwnerID: string; + protected + function GetFlattenedProperties: string; + procedure InternalInvalidateRect(ARect: TRect; Erase: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure SaveAsXIB(const Filename: string); + function getObjectRecord: string; override; + function getAsXIBObject: string; override; + function getConnectionRecords: string; override; + function GetDesigner: IMyWidgetDesigner; override; + property Designer: IMyWidgetDesigner read FDesigner write FDesigner; + published + property FilesOwnerClass: string read FFilesOwnerClass write FFilesOwnerClass stored IsNIBRoot; + property IsHiddenObject: boolean read FIsHiddenObject write FIsHiddenObject stored IsNIBRoot; + property HiddenObjectOutletName: string read FHiddenObjectOutletName write FHiddenObjectOutletName stored IsNIBRoot; + end; + + UIResponder = class(NSObject); + + { UIWindow } + + UIWindow = class(UIView) + private + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); override; + public + constructor Create(AOwner: TComponent); override; + procedure paint(ACanvas: TCanvas); override; + class function GetIBClassName: string; override; + published + end; + + { UIViewController } + + UIViewController = class(tiOSFakeComponent) + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + function GetHeight: integer; override; + function GetWidth: integer; override; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); override; + public + constructor Create(AOwner: TComponent); override; + class function GetIBClassName: string; override; + end; + + { UINavigationBar } + + UINavigationBar = class(UIView) + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); override; + procedure paint(ACanvas: TCanvas); override; + public + constructor Create(AOwner: TComponent); override; + class function GetIBClassName: string; override; + end; + + { UINavigationItem } + + UINavigationItem = class(UIView) + protected + function GetWidth: integer; override; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); override; + public + constructor Create(AOwner: TComponent); override; + class function GetIBClassName: string; override; + end; + + { UINavigationController } + + UINavigationController = class(UIViewController) + private + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + procedure SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); override; + public + constructor Create(AOwner: TComponent); override; + procedure InitializeDefaultChildren; override; + class function GetIBClassName: string; override; + published + end; + + { UIButton } + id = ^objc_object; + TcocoaEvent = procedure(sender: id) of object; + + UIButton = class(UIView) + private + FNSNextKeyView: UIView; + FonTouchDown: TCocoaEvent; + FTextColor: TColor; + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + function WriteToConnectionRecords(AnObjectDomElement: TDOMElement): TDOMElement; override; + public + constructor Create(AOwner: TComponent); override; + class function GetIBClassName: string; override; + + property NSNextKeyView: UIView read FNSNextKeyView write FNSNextKeyView; + published + property TextColor: TColor read FTextColor write FTextColor; + property onTouchDown: TCocoaEvent read FonTouchDown write FonTouchDown; + end; + + { UILabel } + TLineBreaks = (lbWordWrap,lbCharacterMode,lbClip,lbTruncateHead,lbTruncateTail,lbTruncateMiddle); + TiOSFakeAlignment = (alLeft, alCenter, alRight); + + UILabel = class(UIView) + private + FEnabled: boolean; + FFont: TiOSFakeFontDescription; + FHighlighted: boolean; + FLineBreaks: TLineBreaks; + FLines: integer; + FTextAlignment: TiOSFakeAlignment; + FTextColor: TColor; + procedure SetFont(AValue: TiOSFakeFontDescription); + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + class function GetIBClassName: string; override; + procedure paint(ACanvas: TCanvas); override; + published + property Lines: integer read FLines write FLines; + property TextAlignment: TiOSFakeAlignment read FTextAlignment write FTextAlignment; + property TextColor: TColor read FTextColor write FTextColor; + property Font: TiOSFakeFontDescription read FFont write SetFont; + property Enabled: boolean read FEnabled write FEnabled; + property Highlighted: boolean read FHighlighted write FHighlighted; + property LineBreaks: TLineBreaks read FLineBreaks write FLineBreaks; + end; + + { UITextField } + + UITextField = class(UIView) + private + FPlaceholder: string; + FText: string; + FTextAlignment: TiOSFakeAlignment; + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + class function GetIBClassName: string; override; + //procedure paint(ACanvas: TCanvas); override; + published + property Text: string read FText write FText; + property Placeholder: string read FPlaceholder write FPlaceholder; + property Alignment: TiOSFakeAlignment read FTextAlignment write FTextAlignment; + end; + + TiOSFakeSeparatorStyle = (ssNone,ssSingleLine,ssSingleLineEtched); + + { UITableView } + + UITableView = class(UIView) + private + FClipSubviews: boolean; + FRowHeight: float; + FSectionFooterHeight: float; + FSectionHeaderHeight: float; + FSeparatorColor: TColor; + FSeparatorStyle: TiOSFakeSeparatorStyle; + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + class function GetIBClassName: string; override; + published + property RowHeight: float read FRowHeight write FRowHeight; + property SectionHeaderHeight: float read FSectionHeaderHeight write FSectionHeaderHeight; + property SectionFooterHeight: float read FSectionFooterHeight write FSectionFooterHeight; + property SeparatorStyle: TiOSFakeSeparatorStyle read FSeparatorStyle write FSeparatorStyle; + property SeparatorColor: TColor read FSeparatorColor write FSeparatorColor; + property ClipSubviews: boolean read FClipSubviews write FClipSubviews; + end; + + { UISearchBar } + + UISearchBar = class(UIView) + private + FPlaceholder: string; + FPrompt: string; + FText: string; + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + class function GetIBClassName: string; override; + published + property Text: string read FText write FText; + property Placeholder: string read FPlaceholder write FPlaceholder; + property Prompt: string read FPrompt write FPrompt; + end; + + { UIProgressView } + + TiOSFakeProgressViewStyle = (pvUIProgressViewStyleDefault,pvUIProgressViewStyleBar); + + UIProgressView = class(UIView) + private + FProgress: float; + FprogressTintColor: TColor; + FProgressViewStyle: TiOSFakeProgressViewStyle; + FtrackTintColor: TColor; + protected + procedure WriteToDomElement(AnObjectDomElement: TDOMElement); override; + public + constructor Create(AOwner: TComponent); override; + class function GetIBClassName: string; override; + published + property progressViewStyle: TiOSFakeProgressViewStyle read FProgressViewStyle write FprogressViewStyle; + property progress: float read FProgress write FProgress; + property progressTintColor: TColor read FprogressTintColor write FprogressTintColor; + property trackTintColor: TColor read FtrackTintColor write FtrackTintColor; + end; + + +implementation + +uses + fpTemplate, + variants, varutils, + typinfo, +{$ifndef OutsideIDE} + MacroIntf, +{$endif OutsideIDE} + PropEdits, + base64; + +var + GConnectionID: integer; + +{ UIProgressView } + +procedure UIProgressView.WriteToDomElement(AnObjectDomElement: TDOMElement); +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBFloat(AnObjectDomElement,'IBUIProgress',FProgress); + AddIBInt(AnObjectDomElement,'IBUIProgressViewStyle',ord(progressViewStyle),0); + AddIBColor(AnObjectDomElement,'IBUIProgressTintColor',progressTintColor); + AddIBColor(AnObjectDomElement,'IBUITrackTintColor',trackTintColor); +end; + +constructor UIProgressView.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime := false; + FprogressTintColor := clDefault; + FtrackTintColor := clDefault; +end; + +class function UIProgressView.GetIBClassName: string; +begin + Result:='IBUIProgressView'; +end; + +{ UINavigationItem } + +function UINavigationItem.GetWidth: integer; +begin + if assigned(parent) then + result := parent.Width + else + result := 320; +end; + +procedure UINavigationItem.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + inherited SetBounds(Left, Top, Width, Height); +end; + +constructor UINavigationItem.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FHeight:=44; +end; + +class function UINavigationItem.GetIBClassName: string; +begin + Result:='IBUINavigationItem'; +end; + +{ UIViewController } + +procedure UIViewController.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + ASubElement: TDOMElement; + i: Integer; +begin + AddIBString(AnObjectDomElement,'targetRuntimeIdentifier','IBCocoaTouchFramework'); + + for i := 0 to ChildCount-1 do + begin + ASubElement := Children[i].WriteToObject(AnObjectDomElement); + if Children[i] is UIView then + ASubElement.AttribStrings['key']:='IBUIView' + else + ASubElement.AttribStrings['key']:=Children[i].GetIBClassName; + end; +end; + +function UIViewController.GetHeight: integer; +begin + if FHeight<>0 then + result := FHeight + else if assigned(parent) then + result := min(Parent.Height,480) + else + result := 480; +end; + +function UIViewController.GetWidth: integer; +begin + if FWidth <> 0 then + result := FWidth + else if assigned(parent) then + result := min(Parent.Width,320) + else + result := 320; +end; + +procedure UIViewController.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + if (FWidth<>0) or (FHeight<>0) or ((width=320) and (height=480)) then + inherited SetBounds(NewLeft, NewTop, Width, Height) + else + inherited SetBounds(Left, Top, Width, Height) +end; + +constructor UIViewController.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=true; + FObjectID:=GConnectionID; + inc(GConnectionID); + FRef:=random(999999999); +end; + +class function UIViewController.GetIBClassName: string; +begin + Result:='IBUIViewController'; +end; + +{ UINavigationBar } + +procedure UINavigationBar.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + AnElement: TDOMElement; +begin + inherited WriteToDomElement(AnObjectDomElement); + AnElement := AnObjectDomElement.FindNode('NSFrame') as TDOMElement; + if assigned(AnElement) then + AnElement.NodeValue:='{{0, -44}, {0, 44}}'; +end; + +procedure UINavigationBar.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + inherited SetBounds(0, 0, 0, 0); +end; + +procedure UINavigationBar.paint(ACanvas: TCanvas); +begin + // Do not paint; +end; + +constructor UINavigationBar.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; +end; + +class function UINavigationBar.GetIBClassName: string; +begin + Result:='IBUINavigationBar'; +end; + +{ UINavigationController } + +procedure UINavigationController.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + NavigationBarElement: TDOMElement; + ViewControllesArray: TDOMElement; + ViewController: TDOMElement; + NavigationItemElement: TDOMElement; + i: Integer; +begin + AddIBString(AnObjectDomElement,'targetRuntimeIdentifier','IBCocoaTouchFramework'); + + ViewControllesArray := AddIBObject(AnObjectDomElement,'IBUIViewControllers','NSMutableArray'); + AddIBBoolean(ViewControllesArray,'EncodedWithXMLCoder',true); + + for i := 0 to ChildCount-1 do + begin + if Children[i] is UINavigationBar then + begin + NavigationBarElement := Children[i].WriteToObject(AnObjectDomElement); + NavigationBarElement.AttribStrings['key']:=Children[i].GetIBClassName; + end; + if children[i] is UIViewController then + begin + ViewController := children[i].WriteToObject(ViewControllesArray); + AddIBString(ViewController,'targetRuntimeIdentifier','IBCocoaTouchFramework'); + AddIBReference(ViewController,'IBUIParentViewController',self,true); + end; + end; + +end; + +procedure UINavigationController.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + inherited SetBounds(NewLeft, NewTop, Width, Height); +end; + +constructor UINavigationController.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; + FWidth:=320; + FHeight:=480; +end; + +procedure UINavigationController.InitializeDefaultChildren; +var + AChild: tiOSFakeComponent; + AViewController: TComponent; + Designer: IMyWidgetDesigner; +begin + designer := GetDesigner; + if assigned(designer) then + begin + Designer.CreateComponent(self,UINavigationBar,'iOS_Views',0,0,0,0,true); + AViewController := Designer.CreateComponent(self,UIViewController,'iOS_Views',0,0,0,0,true); + Designer.CreateComponent(AViewController,UINavigationItem,'iOS_Views',0,0,0,0,true); + end + else + begin + AChild := UINavigationBar.Create(self); + AChild.Parent := self; + + AViewController := UIViewController.Create(self); + tiOSFakeComponent(AViewController).Parent := self; + + AChild := UINavigationItem.Create(self); + AChild.Parent := tiOSFakeComponent(AViewController); + end +end; + +class function UINavigationController.GetIBClassName: string; +begin + Result:='IBUINavigationController'; +end; + +{ UIWindow } + +procedure UIWindow.WriteToDomElement(AnObjectDomElement: TDOMElement); +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBReference(AnObjectDomElement,'NSWindow',self); + AddIBString(AnObjectDomElement,'targetRuntimeIdentifier','IBCocoaTouchFramework'); + AddIBBoolean(AnObjectDomElement,'IBUIResizesToFullScreen',True); +end; + +procedure UIWindow.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + inherited SetBounds(NewLeft, NewTop, Width, Height); +end; + +constructor UIWindow.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + NSNextResponder:=self; + FWidth:=320; + FHeight:=480; + BackgroundColor:=clWhite; + // Value from template + FObjectID:=2; +end; + +procedure UIWindow.paint(ACanvas: TCanvas); +begin + with ACanvas do + begin + Brush.Style:=bsSolid; + Brush.Color:=BackgroundColor; + // outer frame + Pen.Color:=clRed; + Rectangle(0,0,self.Width,self.Height); + end; +end; + +class function UIWindow.GetIBClassName: string; +begin + Result:='IBUIWindow'; +end; + +{ NSObject } + +procedure NSObject.GetXIBSaveParam(Sender: TObject; const ParamName: String; out AValue: String); +var + i: Integer; +begin + if ParamName='Objects' then + begin + AValue:=getAsXIBObject; + for i := 0 to self.ChildCount-1 do + begin + avalue := AValue + self.Children[i].getAsXIBObject; + end; + end + else if ParamName='flattenedProperties' then + begin + AValue := GetFlattenedProperties; + end + else if ParamName='ConnectionRecords' then + begin + avalue := getConnectionRecords; + for i := 0 to self.ChildCount-1 do + begin + avalue := AValue + self.Children[i].getConnectionRecords; + end; + end + else if ParamName='ObjectRecords' then + begin + AValue := getObjectRecord; + for i := 0 to self.ChildCount-1 do + begin + avalue := AValue + self.Children[i].getObjectRecord; + end; + end; +end; + +function NSObject.IsNIBRoot: boolean; +begin + result := Parent=Nil; +end; + +function NSObject.GetFilesOwnerID: string; +begin + if IsHiddenObject then + Result:='841351856' + else + Result:='664661524'; +end; + +function NSObject.GetFlattenedProperties: string; +var + XMLDoc: TXMLDocument; + AStream: TStringStream; + FlattenedPropertiesElement: TDOMElement; + SortedKeysElements: TDOMElement; + ValuesElements: TDOMElement; + AnElement: TDOMElement; + i: integer; +begin +// assert(self is AppDelegate); + XMLDoc := TXMLDocument.Create; + try + FlattenedPropertiesElement := AddIBObject(XMLDoc,'flattenedProperties','NSMutableDictionary'); + AddIBBoolean(FlattenedPropertiesElement,'EncodedWithXMLCoder',True); + + SortedKeysElements := AddIBObject(FlattenedPropertiesElement,'dict.sortedKeys','NSArray'); + AddIBBoolean(SortedKeysElements,'EncodedWithXMLCoder',True); + // Add props for File's Owner + AddIBString(SortedKeysElements,'','-1.CustomClassName'); + AddIBString(SortedKeysElements,'','-1.IBPluginDependency'); + // Add props for First Responder + AddIBString(SortedKeysElements,'','-2.CustomClassName'); + AddIBString(SortedKeysElements,'','-2.IBPluginDependency'); + AddIBString(SortedKeysElements,'','10.IBPluginDependency'); + AddIBString(SortedKeysElements,'','2.IBAttributePlaceholdersKey'); + AddIBString(SortedKeysElements,'','2.IBPluginDependency'); + if IsHiddenObject then + begin + AddIBString(SortedKeysElements,'','3.CustomClassName'); + AddIBString(SortedKeysElements,'','3.IBPluginDependency'); + end; + for i := 0 to ChildCount -1 do + AddIBString(SortedKeysElements,'',inttostr(Children[i].ObjectID)+'.IBPluginDependency'); + + ValuesElements := AddIBObject(FlattenedPropertiesElement,'dict.values','NSArray'); + AddIBBoolean(ValuesElements,'EncodedWithXMLCoder',True); + // Add props for File's Owner + AddIBString(ValuesElements,'',FilesOwnerClass); + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + // Add props for First Responder + AddIBString(ValuesElements,'','UIResponder'); + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + + AnElement := AddIBObject(ValuesElements,'','NSMutableDictionary'); + AddIBBoolean(AnElement,'EncodedWithXMLCoder',True); + AddIBReference(AnElement,'dict.sortedKeys','0'); + AddIBReference(AnElement,'dict.values','0'); + + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + if IsHiddenObject then + begin + AddIBString(ValuesElements,'',self.ClassName); + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + end; + for i := 0 to ChildCount -1 do + AddIBString(ValuesElements,'','com.apple.InterfaceBuilder.IBCocoaTouchPlugin'); + + AStream := TStringStream.Create(''); + try + for i := 0 to XMLDoc.ChildNodes.Count-1 do + WriteXML(XMLDoc.ChildNodes.Item[i],AStream); + result := AStream.DataString; + finally + AStream.Free; + end; + finally + XMLDoc.Free; + end; +end; + +procedure NSObject.InternalInvalidateRect(ARect: TRect; Erase: boolean); +begin + if (Parent=nil) and (Designer<>nil) then + Designer.InvalidateRect(Self,ARect,Erase); +end; + +function NSObject.getObjectRecord: string; +begin + if IsNIBRoot then + begin + // ObjectRecord's for the File's Owner and First Responder + result := + '' + LineEnding + + ' -1' +LineEnding + + ' ' + LineEnding + + ' ' + LineEnding + + ' File''s Owner' + LineEnding + + '' + LineEnding + + '' + LineEnding + + ' -2' + LineEnding + + ' ' + LineEnding + + ' ' + LineEnding + + ''+ LineEnding; + if IsHiddenObject then + result := result + + '' + LineEnding + + ' 3' + LineEnding + + ' ' + LineEnding + + ' ' + LineEnding + + '' + LineEnding; + end + else + result := inherited getObjectRecord; +end; + +function NSObject.getAsXIBObject: string; +begin + if IsNIBRoot then + begin + // Objects for the File's Owner and First Responder + result := + // File's owner + '' + LineEnding + + ' IBFilesOwner' + LineEnding + + ' IBCocoaTouchFramework' + LineEnding + + '' + LineEnding + + // First responder + '' + LineEnding + + ' IBFirstResponder' + LineEnding + + ' IBCocoaTouchFramework' + LineEnding + + '' + LineEnding; + if IsHiddenObject then + result := result + + '' + LineEnding + + ' IBCocoaTouchFramework' + LineEnding + + '' + LineEnding; + + end + else + result := inherited getObjectRecord; +end; + +function NSObject.getConnectionRecords: string; +begin + if IsNIBRoot then + begin + if IsHiddenObject then + result := result + + '' + LineEnding + + ' ' + LineEnding + + ' '+HiddenObjectOutletName+'' + LineEnding + + ' ' + LineEnding + + ' ' + LineEnding + + ' ' + LineEnding + + ' 4' + LineEnding + + '' + LineEnding; + end + else + Result:=inherited getConnectionRecords; +end; + +constructor NSObject.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FIsHiddenObject:=true; + FHiddenObjectOutletName:='delegate'; + FWidth:=320; + FHeight:=480; +end; + +procedure NSObject.SaveAsXIB(const Filename: string); +var + ATemplate: TFPTemplate; + fs: TFileStream; + s: string; + dir: string; + +begin + ATemplate := TFPTemplate.Create; + try + ATemplate.StartDelimiter:='[{'; + ATemplate.EndDelimiter:='}]'; + +{$ifndef OutsideIDE} + dir := '$PkgDir(iOSDesigner)'; + IDEMacros.SubstituteMacros(dir); +{$else} + dir := '/Users/joost/svn/ccr-components/iosdesigner'; +{$endif OutsideIDE} + if dir <>'' then + ATemplate.FileName:=dir+PathDelim+ 'MainWindow_iPhone.template' + else + raise exception.create('iOSDesigner package could not be found.'); + + ATemplate.OnGetParam :=@GetXIBSaveParam; + s := ATemplate.GetContent; + fs := TFileStream.Create(Filename,fmCreate); + try + fs.Write(s[1],length(s)); + finally + fs.free; + end; + finally + ATemplate.Free; + end; +end; + +function NSObject.GetDesigner: IMyWidgetDesigner; +begin + Result:=Designer; +end; + +{ tiOSFakeComponent } + +procedure tiOSFakeComponent.SetHeight(const AValue: integer); +begin + SetBounds(Left,Top,Width,AValue); +end; + +procedure tiOSFakeComponent.SetLeft(const AValue: integer); +begin + SetBounds(AValue,Top,Width,Height); +end; + +function tiOSFakeComponent.ElementToString(AWriteDomMethod: tiOSWriteDomMethod): string; +var + XMLDoc: TXMLDocument; + AStream: TStringStream; + RootElement: TDOMElement; + i: integer; +begin + XMLDoc := TXMLDocument.Create; + try + RootElement := XMLDoc.CreateElement('root'); + XMLDoc.AppendChild(RootElement); + AWriteDomMethod(RootElement); + + AStream := TStringStream.Create(''); + try + for i := 0 to RootElement.ChildNodes.Count-1 do + WriteXML(RootElement.ChildNodes.Item[i],AStream); + result := AStream.DataString; + finally + AStream.Free; + end; + finally + XMLDoc.Free; + end; +end; + +function tiOSFakeComponent.GetHeight: integer; +begin + result := FHeight; +end; + +function tiOSFakeComponent.GetLeft: integer; +begin + result := FLeft; +end; + +function tiOSFakeComponent.GetTop: integer; +begin + result := FTop; +end; + +function tiOSFakeComponent.GetWidth: integer; +begin + result := FWidth; +end; + +procedure tiOSFakeComponent.SetParentComponent(Value: TComponent); +begin + if Value is tiOSFakeComponent then + Parent:=UIView(Value); +end; + +procedure tiOSFakeComponent.SetParent(const AValue: tiOSFakeComponent); +begin + if FParent=AValue then exit; + if FParent<>nil then begin + Invalidate; + FParent.FChilds.Remove(Self); + end; + FParent:=AValue; + if FParent<>nil then begin + FParent.FChilds.Add(Self); + end; + Invalidate; +end; + +function tiOSFakeComponent.HasParent: Boolean; +begin + Result:=Parent<>nil; +end; + +function tiOSFakeComponent.GetParentComponent: TComponent; +begin + Result:=Parent; +end; + +procedure tiOSFakeComponent.SetTop(const AValue: integer); +begin + SetBounds(Left,AValue,Width,Height); +end; + +procedure tiOSFakeComponent.SetWidth(const AValue: integer); +begin + SetBounds(Left,Top,AValue,Height); +end; + +function tiOSFakeComponent.GetChilds(Index: integer): tiOSFakeComponent; +begin + Result:=tiOSFakeComponent(FChilds[Index]); +end; + +procedure tiOSFakeComponent.GetChildren(Proc: TGetChildProc; Root: TComponent); +var + i: Integer; +begin + for i:=0 to ChildCount-1 do + if Children[i].Owner=Root then + Proc(Children[i]); +end; + +procedure tiOSFakeComponent.InternalInvalidateRect(ARect: TRect; Erase: boolean); +begin + // +end; + +procedure tiOSFakeComponent.AddConnectionRecord(AnObjectDomElement: TDOMElement; AConnectionType, ALabel, AEventType: string); +var + IBConnectionRecordElement : TDOMElement; + IBConnectionElement : TDOMElement; +begin + if name='' then Exit; + IBConnectionRecordElement := AddIBObject(AnObjectDomElement,'','IBConnectionRecord'); + + IBConnectionElement := AddIBObject(IBConnectionRecordElement,'connection',AConnectionType); + + AddIBString(IBConnectionElement,'label',ALabel); + if AEventType<>'' then + begin + AddIBReference(IBConnectionElement,'source',self,True); + AddIBReference(IBConnectionElement,'destination','664661524'); + end + else + begin + AddIBReference(IBConnectionElement,'source','664661524'); + AddIBReference(IBConnectionElement,'destination',self,True); + end; + AddIBInt(IBConnectionRecordElement,'connectionID',GConnectionID); + inc(GConnectionID); + if AEventType<>'' then + AddIBInt(IBConnectionElement,'IBEventType',StrToInt64Def(AEventType,1)); +end; + +procedure tiOSFakeComponent.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + ChildsMutableArray: TDOMElement; + i: Integer; +begin + if ChildCount>0 then + begin + ChildsMutableArray := AddIBObject(AnObjectDomElement,'NSSubviews','NSMutableArray'); + AddIBBoolean(ChildsMutableArray,'EncodedWithXMLCoder',true); + for i := 0 to ChildCount-1 do + Children[i].WriteToObject(ChildsMutableArray); + end; +end; + +function tiOSFakeComponent.WriteToObject(AnObjectDomElement: TDOMElement) : TDOMElement; +var + ClassDomElement: TDOMElement; + AnAttribute: TDOMNode; + +begin + ClassDomElement := AddIBObject(AnObjectDomElement,'',GetIBClassName); + ClassDomElement.AttribStrings['id']:=IntToStr(Ref); + + WriteToDomElement(ClassDomElement); + result := ClassDomElement; +end; + +function tiOSFakeComponent.WriteToConnectionRecords( + AnObjectDomElement: TDOMElement): TDOMElement; +var + i: Integer; +begin + AddConnectionRecord(AnObjectDomElement,'IBCocoaTouchOutletConnection',Name,''); + for i := 0 to ChildCount-1 do + Children[i].WriteToConnectionRecords(AnObjectDomElement); +end; + +function tiOSFakeComponent.WriteToObjectRecord(AnObjectDomElement: TDOMElement + ): TDOMElement; +var + ObjectRecordElement: TDOMElement; + ChildArray: TDOMElement; + i: Integer; +begin + ObjectRecordElement := AddIBObject(AnObjectDomElement,'','IBObjectRecord'); + AddIBInt(ObjectRecordElement,'objectID',ObjectID); + AddIBReference(ObjectRecordElement,'object',self,True); + + if ChildCount>0 then + begin + ChildArray := AddIBObject(ObjectRecordElement,'children','NSMutableArray'); + AddIBBoolean(ChildArray,'EncodedWithXMLCoder',True); + for i := 0 to ChildCount-1 do + AddIBReference(ChildArray,'',Children[i]); + end; + + if assigned(Parent) then + AddIBReference(ObjectRecordElement,'parent',parent) + else + AddIBReference(ObjectRecordElement,'parent','0'); + for i := 0 to ChildCount-1 do + Children[i].WriteToObjectRecord(AnObjectDomElement); + result := ObjectRecordElement; +end; + +class function tiOSFakeComponent.GetIBClassName: string; +begin + result := ''; +end; + +function tiOSFakeComponent.GetDesigner: IMyWidgetDesigner; +begin + if assigned(parent) then + result := parent.GetDesigner + else + result := nil; +end; + +constructor tiOSFakeComponent.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FChilds:=TFPList.Create; +end; + +destructor tiOSFakeComponent.Destroy; +begin + Parent:=nil; + while ChildCount>0 do Children[ChildCount-1].Free; + FreeAndNil(FChilds); + inherited Destroy; +end; + +procedure tiOSFakeComponent.InitializeDefaultChildren; +begin + // Do nothing +end; + +procedure tiOSFakeComponent.paint(ACanvas: TCanvas); +begin + with ACanvas do + begin + Brush.Style:=bsSolid; + Brush.Color:=clLtGray; + // outer frame + Pen.Color:=clRed; + Rectangle(0,0,self.Width,self.Height); + end; +end; + +procedure tiOSFakeComponent.SetBounds(NewLeft, NewTop, NewWidth, NewHeight: integer); +begin + if (Left=NewLeft) and (Top=NewTop) and (Width=NewWidth) and (Height=NewHeight) then + exit; + Invalidate; + FLeft:=NewLeft; + FTop:=NewTop; + FWidth:=NewWidth; + FHeight:=NewHeight; + Invalidate; +end; + +procedure tiOSFakeComponent.InvalidateRect(ARect: TRect; Erase: boolean); +begin + //writeln('TMyWidget.InvalidateRect ',Name,' ',ARect.Left,',',ARect.Top); + ARect.Left:=Max(0,ARect.Left); + ARect.Top:=Max(0,ARect.Top); + ARect.Right:=Min(Width,ARect.Right); + ARect.Bottom:=Max(Height,ARect.Bottom); + if Parent<>nil then begin + Parent.InvalidateRect(ARect,Erase); + end else begin + InternalInvalidateRect(ARect,Erase); + end; +end; + +procedure tiOSFakeComponent.Invalidate; +begin + InvalidateRect(Rect(0,0,Width,Height),false); +end; + +function tiOSFakeComponent.ChildCount: integer; +begin + Result:=FChilds.Count; +end; + +function tiOSFakeComponent.getAsXIBObject: string; +begin + result := ElementToString(@WriteToObject); +end; + +function tiOSFakeComponent.getConnectionRecords: string; +begin + result := ElementToString(@WriteToConnectionRecords); + inherited; +end; + +function tiOSFakeComponent.getObjectRecord: string; + +begin + result := ElementToString(@WriteToObjectRecord); +end; + +function tiOSFakeComponent.AddElement(ADomNode: TDomElement; AName: string): TDOMElement; +begin + result := ADomNode.OwnerDocument.CreateElement(AName); + ADomNode.AppendChild(result); +end; + +function tiOSFakeComponent.AddIBInt(ADomNode: TDOMElement; APropName: string; + APropValue: integer; ADefaultValue: integer): TDOMElement; +begin + if APropValue<>ADefaultValue then + begin + result := AddElement(ADomNode,'int'); + result.AttribStrings['key']:=APropName; + result.TextContent:=inttostr(APropValue); + end; +end; + +function tiOSFakeComponent.AddIBDouble(ADomNode: TDOMElement; APropName: string; APropValue: double): TDOMElement; +begin + result := AddElement(ADomNode,'double'); + result.AttribStrings['key']:=APropName; + result.TextContent:=floattostr(APropValue); +end; + +function tiOSFakeComponent.AddIBFloat(ADomNode: TDOMElement; APropName: string; + APropValue: double; ADefaultValue: double): TDOMElement; +begin + if APropValue<>ADefaultValue then + begin + result := AddElement(ADomNode,'double'); + result.AttribStrings['key']:=APropName; + result.TextContent:=floattostr(APropValue); + end; +end; + +function tiOSFakeComponent.AddIBString(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; +begin + result := AddElement(ADomNode,'string'); + if APropName<>'' then + result.AttribStrings['key']:=APropName; + result.TextContent:=APropValue; +end; + +function tiOSFakeComponent.AddIBReference(ADomNode: TDOMElement;APropName: string; APropValue: tiOSFakeComponent; ForceValue: boolean): TDOMElement; +begin + if assigned(APropValue) then + begin + result := AddElement(ADomNode,'reference'); + if APropName<>'' then + result.AttribStrings['key']:=APropName; + if ForceValue or (APropValue<>self) then + result.AttribStrings['ref']:=inttostr(APropValue.Ref); + end; +end; + +function tiOSFakeComponent.AddIBReference(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; +begin + result := AddElement(ADomNode,'reference'); + result.AttribStrings['key']:=APropName; + result.AttribStrings['ref']:=APropValue; +end; + +function tiOSFakeComponent.AddIBBoolean(ADomNode: TDOMElement; APropName: string; APropValue: Boolean): TDOMElement; +begin + result := AddElement(ADomNode,'bool'); + if APropName<>'' then + result.AttribStrings['key']:=APropName; + if APropValue then + result.TextContent:='YES' + else + result.TextContent:='NO'; +end; + +function tiOSFakeComponent.AddIBBoolean(ADomNode: TDOMElement; APropName: string; APropValue: Boolean; ADefaultValue: boolean): TDOMElement; +begin + if APropValue<>ADefaultValue then + AddIBBoolean(ADomNode,APropName,APropValue); +end; + +function tiOSFakeComponent.AddIBBytes(ADomNode: TDOMElement; APropName: string; APropValue: string): TDOMElement; +begin + if APropValue<>'' then + begin + APropValue:=EncodeStringBase64(APropValue); + while APropValue[length(APropValue)]='=' do + APropValue:=copy(APropValue,1,length(APropValue)-1); + result := AddElement(ADomNode,'bytes'); + result.AttribStrings['key']:=APropName; + result.TextContent:=APropValue; + + end; +end; + +function tiOSFakeComponent.AddIBObject(ADomNode: TDOMElement; APropName: string; AClass: string): TDOMElement; +begin + result := AddElement(ADomNode,'object'); + result.AttribStrings['class']:=AClass; + if APropName<>'' then + result.AttribStrings['key']:=APropName; +end; + +function tiOSFakeComponent.AddIBObject(ADomDocument: TXMLDocument; APropName: string; AClass: string): TDOMElement; +begin + result := ADomDocument.CreateElement('object'); + ADomDocument.AppendChild(result); + result.AttribStrings['class']:=AClass; + if APropName<>'' then + result.AttribStrings['key']:=APropName; +end; + +function tiOSFakeComponent.AddIBColor(ADomNode: TDOMElement; APropName: string; AColor: TColor): TDOMElement; +var + l: longint; + fr,fg,fb: single; + b: byte; + s: string; + AnElement: TDOMElement; +begin + if AColor=clDefault then + Exit; + + l:=ColorToRGB(AColor); + b := l and ($ff0000) shr 16; + fb := b / $ff; + b := l and ($00ff00) shr 8; + fg := b / $ff; + b := l and ($0000ff); + fr := b / $ff; + s := FloatToStr(fr)+' '+FloatToStr(fg)+' '+FloatToStr(fb); + + AnElement := AddIBObject(ADomNode,APropName,'NSColor'); + AddIBInt(AnElement,'NSColorSpace',1); + AddIBBytes(AnElement,'NSRGB',s); +end; + +function tiOSFakeComponent.AddIBFontDescription(ADomNode: TDOMElement; APropName: string; AFontDescription: TiOSFakeFontDescription): TDOMElement; +var + l: longint; + fr,fg,fb: single; + b: byte; + s: string; + AnElement: TDOMElement; +begin + if AFontDescription.FontType<>ftNotSet then + begin + AnElement := AddIBObject(ADomNode,APropName,'IBUIFontDescription'); + AddIBInt(AnElement,'type',ord(AFontDescription.FontType)); + AddIBDouble(AnElement,'pointSize',AFontDescription.pointSize); + end; +end; + + + +{ UISearchBar } + +procedure UISearchBar.WriteToDomElement(AnObjectDomElement: TDOMElement); +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBString(AnObjectDomElement,'IBText',Text); + AddIBString(AnObjectDomElement,'IBPlaceholder',Placeholder); + AddIBString(AnObjectDomElement,'IBPrompt',Prompt); +end; + +constructor UISearchBar.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; +end; + +destructor UISearchBar.Destroy; +begin + inherited Destroy; +end; + +class function UISearchBar.GetIBClassName: string; +begin + Result:='IBUISearchBar'; +end; + +{ UITableView } + +procedure UITableView.WriteToDomElement(AnObjectDomElement: TDOMElement); +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBFloat(AnObjectDomElement,'IBUIRowHeight',RowHeight); + AddIBFloat(AnObjectDomElement,'IBUISectionHeaderHeight',SectionHeaderHeight); + AddIBFloat(AnObjectDomElement,'IBUISectionFooterHeight',SectionFooterHeight); + AddIBInt(AnObjectDomElement,'IBUISeparatorStyle',ord(SeparatorStyle),0); + AddIBColor(AnObjectDomElement,'IBUISeparatorColor',SeparatorColor); + AddIBBoolean(AnObjectDomElement,'IBUIClipsSubviews',ClipSubviews); +end; + +constructor UITableView.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FRowHeight:=44; + FSectionFooterHeight:=22; + FSectionHeaderHeight:=22; + FSeparatorStyle:=ssSingleLine; + FSeparatorColor:=clDefault; + FClipSubviews:=true; + FAcceptChildsAtDesignTime:=false; + FBackgroundColor := clWhite; +end; + +destructor UITableView.Destroy; +begin + inherited Destroy; +end; + +class function UITableView.GetIBClassName: string; +begin + Result:='IBUITableView'; +end; + +{ UITextField } + +procedure UITextField.WriteToDomElement(AnObjectDomElement: TDOMElement); +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBString(AnObjectDomElement,'IBUIText',Text); + AddIBString(AnObjectDomElement,'IBUIPlaceholder',Placeholder); + AddIBInt(AnObjectDomElement,'IBUITextAlignment',ord(Alignment),0) +end; + +constructor UITextField.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; +end; + +destructor UITextField.Destroy; +begin + inherited Destroy; +end; + +class function UITextField.GetIBClassName: string; +begin + Result:='IBUITextField'; +end; + +{ TiOSFakeFontDescription } + +constructor TiOSFakeFontDescription.Create; +begin + pointSize:=12; +end; + +{ TMyLabelButton } + +procedure UILabel.SetFont(AValue: TiOSFakeFontDescription); +begin + if FFont=AValue then Exit; + FFont.Assign(AValue); +end; + +procedure UILabel.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + AnElement: TDOMElement; +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBString(AnObjectDomElement,'IBUIText',Caption); + AddIBInt(AnObjectDomElement,'IBUINumberOfLines',Lines,1); + AddIBInt(AnObjectDomElement,'IBUITextAlignment',ord(TextAlignment),0); + AddIBColor(AnObjectDomElement,'IBUITextColor',TextColor); + AddIBFontDescription(AnObjectDomElement,'IBUIFontDescription',Font); + AddIBBoolean(AnObjectDomElement,'IBUIEnabled',Enabled,True); + AddIBBoolean(AnObjectDomElement,'IBUIHighlighted',Highlighted,false); + AddIBInt(AnObjectDomElement,'IBUILineBreakMode',ord(LineBreaks),4); +end; + + +constructor UILabel.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; + FLines := 1; + FFont := TiOSFakeFontDescription.Create; + FEnabled := true; +end; + +destructor UILabel.Destroy; +begin + FFont.Free; + inherited Destroy; +end; + +class function UILabel.GetIBClassName: string; +begin + result := 'IBUILabel'; +end; + +procedure UILabel.paint(ACanvas: TCanvas); +begin + ACanvas.Font.Color:=TextColor; + case Font.FontType of + ftSystemBold: begin + ACanvas.font.Name:='Helvetica'; + ACanvas.Font.Size:=round(Font.FpointSize); + ACanvas.Font.Bold:=true; + ACanvas.Font.Italic:=False; + end; + ftSystem: begin + ACanvas.font.Name:='Helvetica'; + ACanvas.Font.Size:=round(Font.FpointSize); + ACanvas.Font.Bold:=false; + ACanvas.Font.Italic:=False; + end; + ftSystemItalic: begin + ACanvas.font.Name:='Helvetica'; + ACanvas.Font.Size:=round(Font.FpointSize); + ACanvas.Font.Italic:=true; + ACanvas.Font.Bold:=false; + end + else + begin + ACanvas.font.Name:='Helvetica'; + ACanvas.Font.Size:=12; + ACanvas.Font.Italic:=false; + ACanvas.Font.Bold:=false; + end; + end; + ACanvas.TextOut(5,2,Caption); +end; + + +{ UIView } + +function UIView.GetNSSuperView: UIView; +begin + if assigned(Parent) and (Parent is UIView) then + result := uiview(parent).GetNSSuperView + else + result := self; +end; + +procedure UIView.SetCaption(const AValue: string); +begin + if FCaption=AValue then exit; + FCaption:=AValue; + Invalidate; +end; + +procedure UIView.SetName(const NewName: TComponentName); +begin + if Name=Caption then Caption:=NewName; + inherited SetName(NewName); +end; + +procedure UIView.WriteToDomElement(AnObjectDomElement: TDOMElement); +var + b: integer; +begin + AddIBString(AnObjectDomElement,'NSFrame','{{'+inttostr(Left)+', '+inttostr(top)+'}, {'+inttostr(width)+', '+inttostr(height)+'}}'); + AddIBReference(AnObjectDomElement,'NSSuperview',NSSuperview); + AddIBReference(AnObjectDomElement,'NSNextResponder',NSNextResponder); + AddIBBoolean(AnObjectDomElement,'IBUIOpaque',Opaque); + b := 1316; //1325; + if Hidden then + b := b or (1 shl 31); + AddIBInt(AnObjectDomElement,'NSvFlags',b); + AddIBFloat(AnObjectDomElement,'IBUIAlpha',Alpha,1); + AddIBColor(AnObjectDomElement,'IBUIBackgroundColor',BackgroundColor); + inherited WriteToDomElement(AnObjectDomElement); +end; + +constructor UIView.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FObjectID:=GConnectionID; + inc(GConnectionID); + FRef:=random(999999999); + FAcceptChildsAtDesignTime:=true; + FAlpha:=1; + FBackgroundColor:=clDefault; +end; + +procedure UIView.paint(ACanvas: TCanvas); +begin + with ACanvas do + begin + Brush.Style:=bsSolid; + Brush.Color:=BackgroundColor; + // outer frame + Pen.Color:=clRed; + Rectangle(0,0,self.Width,self.Height); + // caption + Font.Color:=clBlack; + Font.Name:='Helvetica'; + Font.Size:=12; + Font.Italic:=false; + Font.Bold:=false; + TextOut(5,2,Caption); + end; +end; + +class function UIView.GetIBClassName: string; +begin + result := 'IBUIView'; +end; + +{ UIButton } + +procedure UIButton.WriteToDomElement(AnObjectDomElement: TDOMElement); + +begin + inherited WriteToDomElement(AnObjectDomElement); + AddIBReference(AnObjectDomElement,'NSNextKeyView',NSNextKeyView); + AddIBInt(AnObjectDomElement,'IBUIButtonType',1); + AddIBString(AnObjectDomElement,'IBUINormalTitle',Caption); + AddIBColor(AnObjectDomElement,'IBUINormalTitleColor',TextColor); +end; + +function UIButton.WriteToConnectionRecords(AnObjectDomElement: TDOMElement): TDOMElement; +var + AMethod: TMethod; +begin + inherited WriteToConnectionRecords(AnObjectDomElement); + //writeln('PROPVAL: ' + vartostr(GetPropValue(self,'onTouchDown'))); + AMethod := LazGetMethodProp(self,GetPropInfo(self,'onTouchDown')); + + writeln('PROPVAL: ' + hexStr(PtrInt( AMethod.Code),8) + ' - ' + hexStr(ptrint(AMethod.Data),8)); + if AMethod.Data<>nil then + begin + AddConnectionRecord(AnObjectDomElement,'IBCocoaTouchEventConnection',Name+'TouchDown:','1'); + writeln(TObject(AMethod.Data).MethodName(self)); + end + else + writeln('AA- Geen Touchdown ' + self.Name); +end; + +constructor UIButton.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FAcceptChildsAtDesignTime:=false; +end; + +class function UIButton.GetIBClassName: string; +begin + result := 'IBUIButton'; +end; + +initialization + GConnectionID:=50; +end. + diff --git a/components/iosdesigner/iosdesigner.lpk b/components/iosdesigner/iosdesigner.lpk new file mode 100644 index 000000000..c565eb844 --- /dev/null +++ b/components/iosdesigner/iosdesigner.lpk @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/iosdesigner/iosdesigner.pas b/components/iosdesigner/iosdesigner.pas new file mode 100644 index 000000000..e3fc3db81 --- /dev/null +++ b/components/iosdesigner/iosdesigner.pas @@ -0,0 +1,22 @@ +{ This file was automatically created by Lazarus. Do not edit! + This source is only used to compile and install the package. + } + +unit iOSDesigner; + +interface + +uses + iOSNIBDesigner, iOS_Views, iOSIdeIntf, LazarusPackageIntf; + +implementation + +procedure Register; +begin + RegisterUnit('iOSNIBDesigner', @iOSNIBDesigner.Register); + RegisterUnit('iOSIdeIntf', @iOSIdeIntf.Register); +end; + +initialization + RegisterPackage('iOSDesigner', @Register); +end. diff --git a/components/iosdesigner/iosideintf.pas b/components/iosdesigner/iosideintf.pas new file mode 100644 index 000000000..e3ab187d7 --- /dev/null +++ b/components/iosdesigner/iosideintf.pas @@ -0,0 +1,297 @@ +unit iOSIdeIntf; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, Forms, ProjectIntf, iPhoneExtOptions; + +type + + { TiOSApplicationDescriptor } + + TiOSApplicationDescriptor = class(TProjectDescriptor) + public + constructor Create; override; + function GetLocalizedName: string; override; + function GetLocalizedDescription: string; override; + function InitProject(AProject: TLazProject): TModalResult; override; + function CreateStartFiles(AProject: TLazProject): TModalResult; override; + end; + + { TiOSObjectDelegateWindowFileDesc } + + TiOSObjectDelegateWindowFileDesc = class(TFileDescPascalUnitWithResource) + protected + function GetDelegateProtocols: string; virtual; + public + constructor Create; override; + function GetInterfaceUsesSection: string; override; + function GetImplementationSource(const Filename, SourceName, ResourceName: string): string;override; + function GetInterfaceSource(const Filename, SourceName, ResourceName: string): string; override; + function GetUnitDirectives: string; override; + function GetLocalizedName: string; override; + function GetLocalizedDescription: string; override; + end; + + + { TiOSAppDelegateWindowFileDesc } + + TiOSAppDelegateWindowFileDesc = class(TiOSObjectDelegateWindowFileDesc) + protected + function GetDelegateProtocols: string; override; + public + constructor Create; override; + end; + + { TiOSInfo_PlistFileDesc } + + TiOSInfo_PlistFileDesc = class(TProjectFileDescriptor) + public + constructor Create; override; + function CreateSource(const Filename, SourceName, ResourceName: string): string; override; + end; + +var + GiOSApplicationDescriptor: TiOSApplicationDescriptor; + GiOSAppDelegateWindowFileDesc: TiOSAppDelegateWindowFileDesc; + GiOSInfo_PlistFileDesc: TiOSInfo_PlistFileDesc; + GiOSObjectDelegateWindowFileDesc: TiOSObjectDelegateWindowFileDesc; + +procedure register; + +implementation + +uses LazIDEIntf, Controls, iOS_Views; + +procedure register; +begin + GiOSApplicationDescriptor:=TiOSApplicationDescriptor.Create; + RegisterProjectDescriptor(GiOSApplicationDescriptor); + GiOSAppDelegateWindowFileDesc:=TiOSAppDelegateWindowFileDesc.Create; + RegisterProjectFileDescriptor(GiOSAppDelegateWindowFileDesc); + GiOSInfo_PlistFileDesc:=TiOSInfo_PlistFileDesc.Create; + RegisterProjectFileDescriptor(GiOSInfo_PlistFileDesc); + GiOSObjectDelegateWindowFileDesc:=TiOSObjectDelegateWindowFileDesc.Create; + RegisterProjectFileDescriptor(GiOSObjectDelegateWindowFileDesc); + +end; + +{ TiOSObjectDelegateWindowFileDesc } + +function TiOSObjectDelegateWindowFileDesc.GetDelegateProtocols: string; +begin + result := ''; +end; + +constructor TiOSObjectDelegateWindowFileDesc.Create; +begin + inherited Create; + Name:='iOS NIB-Delegate'; + ResourceClass:=NSObject; + UseCreateFormStatements:=false; + VisibleInNewDialog:=true; +end; + +function TiOSObjectDelegateWindowFileDesc.GetInterfaceUsesSection: string; +begin + Result:='iPhoneAll'; +end; + +function TiOSObjectDelegateWindowFileDesc.GetImplementationSource( + const Filename, SourceName, ResourceName: string): string; +begin + Result:='procedure T'+ResourceName+'.dealloc;' + LineEnding + + 'begin' + LineEnding + + ' inherited dealloc;' + LineEnding + + 'end;' + LineEnding + + LineEnding + + '{$R *.lfm}' + LineEnding + LineEnding; +end; + +function TiOSObjectDelegateWindowFileDesc.GetInterfaceSource(const Filename, SourceName, ResourceName: string): string; +var + DelegateProtocol: string; +begin + DelegateProtocol:=GetDelegateProtocols; + if DelegateProtocol<>'' then + DelegateProtocol:=','+DelegateProtocol; + Result:= + 'type'+LineEnding + +' T'+ResourceName+' = objcclass('+ResourceClass.ClassName+DelegateProtocol+')'+LineEnding + +' private'+LineEnding + +' { private declarations }'+LineEnding + +' public'+LineEnding + +' procedure dealloc; override;'+LineEnding + +' end;'+LineEnding + +LineEnding; +end; + +function TiOSObjectDelegateWindowFileDesc.GetUnitDirectives: string; +begin + Result:='{$modeswitch ObjectiveC1}'; +end; + +function TiOSObjectDelegateWindowFileDesc.GetLocalizedName: string; +begin + Result:='iOS NIB Delegate'; +end; + +function TiOSObjectDelegateWindowFileDesc.GetLocalizedDescription: string; +begin + Result:='Create a new iOS-NIB file with a delegate to handle it''s contents. '+ + 'The contents of the NIB can be changed with the designer.'; +end; + +{ TiOSInfo_PlistFileDesc } + +constructor TiOSInfo_PlistFileDesc.Create; +begin + inherited Create; + Name:='Info_Plist'; + DefaultFilename:='Info.Plist'; + IsPascalUnit:=false; + VisibleInNewDialog:=false; +end; + +function TiOSInfo_PlistFileDesc.CreateSource(const Filename, SourceName, ResourceName: string): string; +begin + Result:='' + LineEnding + + '' + LineEnding + + '' + LineEnding + + '' + LineEnding + + ' CFBundleDevelopmentRegion' + LineEnding + + ' en' + LineEnding + + ' CFBundleDisplayName' + LineEnding + + ' ${PRODUCT_NAME}' + LineEnding + + ' CFBundleExecutable' + LineEnding + + ' ${EXECUTABLE_NAME}' + LineEnding + + ' CFBundleIconFile' + LineEnding + + ' ' + LineEnding + + ' CFBundleIdentifier' + LineEnding + + ' CNOC.${PRODUCT_NAME:rfc1034identifier}' + LineEnding + + ' CFBundleInfoDictionaryVersion' + LineEnding + + ' 6.0' + LineEnding + + ' CFBundleName' + LineEnding + + ' ${PRODUCT_NAME}' + LineEnding + + ' CFBundlePackageType' + LineEnding + + ' APPL' + LineEnding + + ' CFBundleShortVersionString' + LineEnding + + ' 1.0' + LineEnding + + ' CFBundleSignature' + LineEnding + + ' ????' + LineEnding + + ' CFBundleVersion' + LineEnding + + ' 1.0' + LineEnding + + ' LSRequiresIPhoneOS' + LineEnding + + ' ' + LineEnding + + ' NSMainNibFile' + LineEnding + + ' MainWindow_iPhone' + LineEnding + + ' NSMainNibFile~ipad' + LineEnding + + ' MainWindow_iPad' + LineEnding + + ' UISupportedInterfaceOrientations' + LineEnding + + ' ' + LineEnding + + ' UIInterfaceOrientationLandscapeLeft' + LineEnding + + ' UIInterfaceOrientationLandscapeRight' + LineEnding + + ' UIInterfaceOrientationPortrait' + LineEnding + + ' ' + LineEnding + + ' UISupportedInterfaceOrientations~ipad' + LineEnding + + ' ' + LineEnding + + ' UIInterfaceOrientationPortrait' + LineEnding + + ' UIInterfaceOrientationPortraitUpsideDown' + LineEnding + + ' UIInterfaceOrientationLandscapeLeft' + LineEnding + + ' UIInterfaceOrientationLandscapeRight' + LineEnding + + ' ' + LineEnding + + '' + LineEnding + + ''+LineEnding+LineEnding; +end; + +{ TiOSAppDelegateWindowFileDesc } + +function TiOSAppDelegateWindowFileDesc.GetDelegateProtocols: string; +begin + Result:='UIApplicationDelegateProtocol'; +end; + +constructor TiOSAppDelegateWindowFileDesc.Create; +begin + inherited Create; + Name:='iOS UIApplicationDelegate'; + VisibleInNewDialog:=false; +end; + +{ TiOSApplicationDescriptor } + +constructor TiOSApplicationDescriptor.Create; +begin + inherited Create; + Name := 'iOS application'; +end; + +function TiOSApplicationDescriptor.GetLocalizedName: string; +begin + Result := 'iOS application'; +end; + +function TiOSApplicationDescriptor.GetLocalizedDescription: string; +begin + Result:='iOS application'#13#13'An iOS program ' + +'designed in Lazarus without using the LCL. The program file is ' + +'automatically maintained by Lazarus.'; +end; + +function TiOSApplicationDescriptor.InitProject(AProject: TLazProject): TModalResult; +var + NewSource: String; + MainFile: TLazProjectFile; +begin + inherited InitProject(AProject); + + MainFile:=AProject.CreateProjectFile('iosapp.lpr'); + MainFile.IsPartOfProject:=true; + AProject.AddFile(MainFile,false); + AProject.MainFileID:=0; + + // create program source + NewSource:='program iosapp;' + LineEnding + + LineEnding + + '{$modeswitch ObjectiveC1}' + LineEnding + + LineEnding + + 'uses' + LineEnding + + ' iPhoneAll, AppDelegate_iPhoneU;' + LineEnding + + LineEnding + + 'var' + LineEnding + + ' pool : NSAutoreleasePool;' + LineEnding + + 'begin' + LineEnding + + ' pool := NSAutoreleasePool.alloc.init;' + LineEnding + + ' UIApplicationMain(argc, argv, nil, nil);' + LineEnding + + ' pool.release;' + LineEnding + + 'end.' + LineEnding + LineEnding; + + AProject.MainFile.SetSourceText(NewSource); + + // add + AProject.AddPackageDependency('FCL'); + + // compiler options + AProject.LazCompilerOptions.Win32GraphicApp:=false; + + //AProject.LazCompilerOptions.CustomOptions:='-XR/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk'; + AProject.LazCompilerOptions.TargetOS:='iphonesim'; + AProject.Flags := AProject.Flags - [pfMainUnitHasCreateFormStatements]; + Result:= mrOK; +end; + +function TiOSApplicationDescriptor.CreateStartFiles(AProject: TLazProject): TModalResult; +begin + //LazarusIDE.DoSaveAll([sfProjectSaving]); + GiOSAppDelegateWindowFileDesc.DefaultResourceName:='AppDelegate_iPhone'; + LazarusIDE.DoNewEditorFile(GiOSAppDelegateWindowFileDesc,'appdelegate_iphoneu.pas','',[nfIsPartOfProject,nfOpenInEditor,nfCreateDefaultSrc]); + result := mrOK; + ProjOptions.isIPhoneApp:=true; + ProjOptions.MainNib:='appdelegate_iphoneu'; + ProjOptions.Save; +end; + +end. + diff --git a/components/iosdesigner/iosnibdesigner.pas b/components/iosdesigner/iosnibdesigner.pas new file mode 100644 index 000000000..f32365fd4 --- /dev/null +++ b/components/iosdesigner/iosnibdesigner.pas @@ -0,0 +1,333 @@ +{ iOS NOB-designer for the Lazarus IDE + + Copyright (C) 2012 Joost van der Sluis joost@cnoc.nl + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version with the following modification: + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules,and + to copy and distribute the resulting executable under terms of your choice, + provided that you also meet, for each linked independent module, the terms + and conditions of the license of that module. An independent module is a + module which is not derived from or based on this library. If you modify + this library, you may extend this exception to your version of the library, + but you are not obligated to do so. If you do not wish to do so, delete this + exception statement from your version. + + 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. See the GNU Library General Public License + for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +} + +unit iOSNIBDesigner; + +{$mode objfpc}{$H+} +{$typeinfo off} + +interface + +uses + LCLProc, LCLType, Classes, SysUtils, FormEditingIntf, LCLIntf, Graphics, propedits, CodeToolManager, + ProjectIntf, + iOS_Views, + dom, + IDEIntf, + IDEWindowIntf, + LazIDEIntf, + Dialogs, +{$ifndef OutsideIDE} + CustomNonFormDesigner, +{$endif OutsideIDE} + Controls, + ComponentReg, + typinfo, + forms; + +type + + { TNSObjectDesignerMediator } + + TNSObjectDesignerMediator = class(TDesignerMediator,IMyWidgetDesigner) + private + FMyForm: NSObject; + procedure DoOnLoadBounds(Sender: TObject); + protected + procedure SetLCLForm(const AValue: TForm); override; + public + procedure SaveToXIB(AForm: NSObject); + // needed by the lazarus form editor + class function CreateMediator(TheOwner, aForm: TComponent): TDesignerMediator; override; + class function FormClass: TComponentClass; override; + procedure GetBounds(AComponent: TComponent; out CurBounds: TRect); override; + procedure SetBounds(AComponent: TComponent; NewBounds: TRect); override; + procedure GetClientArea(AComponent: TComponent; out CurClientArea: TRect; out ScrollOffset: TPoint); override; + procedure Paint; override; + function ComponentIsIcon(AComponent: TComponent): boolean; override; + function ParentAcceptsChild(Parent: TComponent; Child: TComponentClass): boolean; override; + procedure InitComponent(AComponent, NewParent: TComponent; NewBounds: TRect); override; + function CreateComponent(ParentComp: TComponent; + TypeClass: TComponentClass; + const AUnitName: shortstring; + X,Y,W,H: Integer; + DisableAutoSize: boolean): TComponent; + public + // needed by UIView + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure InvalidateRect(Sender: TObject; ARect: TRect; Erase: boolean); + property MyForm: NSObject read FMyForm; + end; + + { TUIResponderDesignerMediator } + + TUIResponderDesignerMediator = class(TNSObjectDesignerMediator) + public + class function FormClass: TComponentClass; override; + end; + +procedure Register; + +implementation + +procedure Register; + + procedure SetFakeUnitname(AClass: TClass); + var + ATypInfo: PTypeInfo; + ATypData: PTypeData; + begin + ATypInfo:=PTypeInfo(AClass.ClassInfo); + ATypData:=GetTypeData(ATypInfo); + + ATypData^.UnitName[1]:='i'; + ATypData^.UnitName[2]:='P'; + ATypData^.UnitName[3]:='h'; + ATypData^.UnitName[4]:='o'; + ATypData^.UnitName[5]:='n'; + ATypData^.UnitName[6]:='e'; + ATypData^.UnitName[7]:='A'; + ATypData^.UnitName[8]:='l'; + ATypData^.UnitName[9]:='l'; + end; + +begin + FormEditingHook.RegisterDesignerMediator(TNSObjectDesignerMediator); + FormEditingHook.RegisterDesignerMediator(TUIResponderDesignerMediator); + RegisterComponents('iOS',[UIWindow,UINavigationController,UIButton,UILabel,UITextField,UITableView,UISearchBar,UIView,UIViewController, UIProgressView]); + + RegisterClass(UINavigationItem); + RegisterClass(UIViewController); + RegisterClass(UINavigationBar); + + // This is a hack to overwrite the unitname RTTI-information of these objects. + // This is to make sure that the Codetools add the right unit-name to the + // source when an object is added to the NIB-file. + SetFakeUnitname(UIButton); + SetFakeUnitname(UILabel); + SetFakeUnitname(UITextField); + SetFakeUnitname(UITableView); + SetFakeUnitname(UISearchBar); + SetFakeUnitname(UIWindow); + SetFakeUnitname(UIView); + SetFakeUnitname(UINavigationController); + SetFakeUnitname(UIViewController); + SetFakeUnitname(UIProgressView); +end; + +{ TNSObjectDesignerMediator } + +constructor TNSObjectDesignerMediator.Create(AOwner: TComponent); +begin + inherited Create(AOwner); +end; + +destructor TNSObjectDesignerMediator.Destroy; +begin + if FMyForm<>nil then FMyForm.Designer:=nil; + FMyForm:=nil; + inherited Destroy; +end; + +procedure TNSObjectDesignerMediator.DoOnLoadBounds(Sender: TObject); +begin + //debugln('----onsaveloadbounds--------'); + SaveToXIB(FMyForm); +end; + +procedure TNSObjectDesignerMediator.SetLCLForm(const AValue: TForm); +begin +{$ifndef OutsideIDE} + if assigned(LCLForm) then + TCustomNonFormDesignerForm(LCLForm).OnSaveBounds:=nil; +{$endif OutsideIDE} + inherited SetLCLForm(AValue); +{$ifndef OutsideIDE} + if assigned(LCLForm) then + TCustomNonFormDesignerForm(LCLForm).OnSaveBounds:=@DoOnLoadBounds; +{$endif OutsideIDE} +end; + +procedure TNSObjectDesignerMediator.SaveToXIB(AForm: NSObject); +var + AFileName: string; + AResourcesPath: string; + ALazFile: TLazProjectFile; +begin + ALazFile := LazarusIDE.GetProjectFileWithRootComponent(AForm); + if assigned(ALazFile) then + begin + AFileName:=ChangeFileExt(ALazFile.Filename,'.xib'); + AResourcesPath:=ExtractFilePath(AFileName)+'Resources'; + ForceDirectories(AResourcesPath); + AFileName:=AResourcesPath+PathDelim+ExtractFileName(AFileName); + AForm.SaveAsXIB(AFileName); + //DebugLn('XIB saved: '+AFileName); + end; +end; + +class function TNSObjectDesignerMediator.CreateMediator(TheOwner, aForm: TComponent): TDesignerMediator; +var + Mediator: TNSObjectDesignerMediator; +begin + Result:=inherited CreateMediator(TheOwner,aForm); + Mediator:=TNSObjectDesignerMediator(Result); + Mediator.FMyForm:=aForm as NSObject; + Mediator.FMyForm.Designer:=Mediator; +end; + +class function TNSObjectDesignerMediator.FormClass: TComponentClass; +begin + Result:=NSObject; +end; + +procedure TNSObjectDesignerMediator.GetBounds(AComponent: TComponent; out CurBounds: TRect); +var + w: tiOSFakeComponent; +begin + if AComponent is tiOSFakeComponent then begin + w:=tiOSFakeComponent(AComponent); + CurBounds:=Bounds(w.Left,w.Top,w.Width,w.Height); + end else + inherited GetBounds(AComponent,CurBounds); +end; + +procedure TNSObjectDesignerMediator.InvalidateRect(Sender: TObject; ARect: TRect; Erase: boolean); +begin + if (LCLForm=nil) or (not LCLForm.HandleAllocated) then exit; + LCLIntf.InvalidateRect(LCLForm.Handle,@ARect,Erase); +end; + +procedure TNSObjectDesignerMediator.SetBounds(AComponent: TComponent; NewBounds: TRect); +begin + if AComponent is tiOSFakeComponent then begin + tiOSFakeComponent(AComponent).SetBounds(NewBounds.Left,NewBounds.Top, + NewBounds.Right-NewBounds.Left,NewBounds.Bottom-NewBounds.Top); + end else + inherited SetBounds(AComponent,NewBounds); +end; + +procedure TNSObjectDesignerMediator.GetClientArea(AComponent: TComponent; out CurClientArea: TRect; out ScrollOffset: TPoint); +var + Widget: tiOSFakeComponent; +begin + if AComponent is tiOSFakeComponent then begin + Widget:=tiOSFakeComponent(AComponent); + CurClientArea:=Rect(0,0, + Widget.Width, + Widget.Height); + ScrollOffset:=Point(0,0); + end else + inherited GetClientArea(AComponent, CurClientArea, ScrollOffset); +end; + +procedure TNSObjectDesignerMediator.Paint; + + procedure PaintWidget(AWidget: tiOSFakeComponent); + var + i: Integer; + Child: tiOSFakeComponent; + begin + with LCLForm.Canvas do + begin + if AWidget is NSObject then + begin + Brush.Style:=bsClear; + Brush.Color:=clLtGray; + Pen.Color:=clMaroon; + Rectangle(0,0,AWidget.Width,AWidget.Height); + end + else + begin + AWidget.Paint(LCLForm.Canvas); + end; + // children + if AWidget.ChildCount>0 then + begin + //SaveHandleState; + // clip client area + {if IntersectClipRect(Handle, AWidget.left, AWidget.Top, AWidget.left+AWidget.Width, + AWidget.Height+AWidget.Top)<>NullRegion + then} begin + for i:=0 to AWidget.ChildCount-1 do begin + SaveHandleState; + Child:=AWidget.Children[i]; + // clip child area + MoveWindowOrgEx(Handle,Child.Left,Child.Top); + if IntersectClipRect(Handle,0,0,Child.Width,Child.Height)<>NullRegion then + PaintWidget(Child); + RestoreHandleState; + end; + end; + //RestoreHandleState; + end; + end; + end; + +begin + PaintWidget(MyForm); + inherited Paint; +end; + +function TNSObjectDesignerMediator.ComponentIsIcon(AComponent: TComponent): boolean; +begin + Result:=not (AComponent is tiOSFakeComponent); +end; + +function TNSObjectDesignerMediator.ParentAcceptsChild(Parent: TComponent; Child: TComponentClass): boolean; +begin + Result:=(Parent is tiOSFakeComponent) and (Child.InheritsFrom(tiOSFakeComponent)) + and (tiOSFakeComponent(Parent).AcceptChildsAtDesignTime); +end; + +procedure TNSObjectDesignerMediator.InitComponent(AComponent, NewParent: TComponent; NewBounds: TRect); +begin + inherited InitComponent(AComponent, NewParent, NewBounds); + if AComponent is tiOSFakeComponent then + tiOSFakeComponent(AComponent).InitializeDefaultChildren; +end; + +function TNSObjectDesignerMediator.CreateComponent(ParentComp: TComponent; + TypeClass: TComponentClass; const AUnitName: shortstring; X, Y, W, + H: Integer; DisableAutoSize: boolean): TComponent; +begin + result := FormEditingHook.CreateComponent(ParentComp,TypeClass,AUnitName,x,y,w,h,DisableAutoSize); +end; + +{ TUIResponderDesignerMediator } + +class function TUIResponderDesignerMediator.FormClass: TComponentClass; +begin + Result:=UIResponder; +end; + +end. +