From 2ef75319f9b3268a3304866cbbb165485570d545 Mon Sep 17 00:00:00 2001 From: Lucas Moura Belo Date: Tue, 22 Dec 2020 15:46:17 -0300 Subject: [PATCH 1/4] Delphi FMX wrappers registration --- Source/fmx/WrapDelphiFmx.pas | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Source/fmx/WrapDelphiFmx.pas diff --git a/Source/fmx/WrapDelphiFmx.pas b/Source/fmx/WrapDelphiFmx.pas new file mode 100644 index 00000000..5bd1b3b5 --- /dev/null +++ b/Source/fmx/WrapDelphiFmx.pas @@ -0,0 +1,23 @@ +unit WrapDelphiFmx; + +interface + +implementation + +uses + WrapDelphiTypes, + WrapDelphiClasses, + WrapDelphiWindows, + WrapFireDac, + WrapFmxTypes, + WrapFmxStdCtrls, + WrapFmxActnList, + WrapFmxComCtrls, + WrapFmxDialogs, + WrapFmxForms, + WrapFmxShapes, + WrapFmxLayouts, + WrapFmxScrollBox, + WrapFmxGrids; + +end. From 11b60f795535ba831805e64aa442e83db3c152ed Mon Sep 17 00:00:00 2001 From: Lucas Moura Belo Date: Tue, 22 Dec 2020 16:13:18 -0300 Subject: [PATCH 2/4] Creational mechanism for resourced and non-resourced FMX forms --- Source/fmx/WrapFmxForms.pas | 54 +++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/Source/fmx/WrapFmxForms.pas b/Source/fmx/WrapFmxForms.pas index 646bfd03..785346fc 100644 --- a/Source/fmx/WrapFmxForms.pas +++ b/Source/fmx/WrapFmxForms.pas @@ -5,7 +5,8 @@ interface uses - FMX.Forms, PythonEngine, WrapDelphiClasses, WrapFmxTypes, WrapFmxControls; + System.Classes, FMX.Forms, + PythonEngine, WrapFmxTypes, WrapDelphiClasses, WrapFmxControls; type TPyDelphiApplication = class(TPyDelphiComponent) @@ -23,7 +24,9 @@ TPyDelphiCommonCustomForm = class(TPyDelphiFmxObject) private function GetDelphiObject: TCommonCustomForm; procedure SetDelphiObject(const Value: TCommonCustomForm); + function HasFormRes(const AClass: TClass): boolean; public + function CreateComponent(AOwner: TComponent): TComponent; override; // Class methods class function DelphiObjectClass: TClass; override; // Properties @@ -88,7 +91,7 @@ TPyDelphiScreen = class(TPyDelphiComponent) implementation uses - WrapDelphi; + WrapDelphi, System.Types; { Register the wrappers, the globals and the constants } type @@ -153,6 +156,46 @@ procedure TPyDelphiApplication.SetDelphiObject(const Value: TApplication); { TPyDelphiCommonCustomForm } +function TPyDelphiCommonCustomForm.CreateComponent( + AOwner: TComponent): TComponent; +type + TCommonCustomFormClass = class of TCommonCustomForm; +var + LClass: TClass; + LFormClass: TCommonCustomFormClass; + LClassName: string; +begin + //if we have a subclass of our Form wrapper, then check if we can find a + //Delphi class that would have the same name as the Python class. + //This would allow Python to instanciate an existing Delphi form class, + //insted of only using a blank form. + if (ob_type <> PythonType.TheTypePtr) then begin + LClassName := string(ob_type.tp_name); + LClass := GetClass(LClassName); + if not Assigned(LClass) then + LClass := GetClass('T' + LClassName); + if Assigned(LClass) and LClass.InheritsFrom(TCommonCustomForm) then + LFormClass := TCommonCustomFormClass(LClass); + end else begin + //get de default form class + if DelphiObjectClass.InheritsFrom(TCommonCustomForm) then + LFormClass := TCommonCustomFormClass(DelphiObjectClass); + end; + + //if it's not a design form, so we create it as a non-resourced form, + //using the non-resourced constructor. + //if the Owner is TApplication, then we have to call its CreateForm method, + //otherwise we won't have a mian form defined, as the main form is the first + //created form. Of course, this is a concern only when Python controls all the + //GUI and calls Apllication.Run by itself. + if not HasFormRes(LFormClass) then + Result := LFormClass.CreateNew(AOwner) + else if (AOwner = Application) then + Application.CreateForm(LFormClass, Result) + else + Result := LFormClass.Create(AOwner); +end; + class function TPyDelphiCommonCustomForm.DelphiObjectClass: TClass; begin Result := TCommonCustomForm; @@ -163,6 +206,13 @@ function TPyDelphiCommonCustomForm.GetDelphiObject: TCommonCustomForm; Result := TCommonCustomForm(inherited DelphiObject); end; +function TPyDelphiCommonCustomForm.HasFormRes(const AClass: TClass): boolean; +begin + Result := FindResource( + FindResourceHInstance(FindClassHInstance(AClass)), + PChar(AClass.ClassName), PChar(RT_RCDATA)) <> 0; +end; + procedure TPyDelphiCommonCustomForm.SetDelphiObject( const Value: TCommonCustomForm); begin From 3027ed1ee225c9586f7c9feb8206912594a9f6fb Mon Sep 17 00:00:00 2001 From: Lucas Moura Belo Date: Tue, 22 Dec 2020 17:18:29 -0300 Subject: [PATCH 3/4] FMX form class validation --- Source/fmx/WrapFmxForms.pas | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Source/fmx/WrapFmxForms.pas b/Source/fmx/WrapFmxForms.pas index 785346fc..9e463e61 100644 --- a/Source/fmx/WrapFmxForms.pas +++ b/Source/fmx/WrapFmxForms.pas @@ -5,7 +5,7 @@ interface uses - System.Classes, FMX.Forms, + System.Classes, System.SysUtils, FMX.Forms, PythonEngine, WrapFmxTypes, WrapDelphiClasses, WrapFmxControls; type @@ -88,6 +88,8 @@ TPyDelphiScreen = class(TPyDelphiComponent) property DelphiObject: TScreen read GetDelphiObject write SetDelphiObject; end; + EInvalidFormClass = class(Exception); + implementation uses @@ -165,6 +167,11 @@ TCommonCustomFormClass = class of TCommonCustomForm; LFormClass: TCommonCustomFormClass; LClassName: string; begin + LFormClass := nil; + //get de default form class + if DelphiObjectClass.InheritsFrom(TCommonCustomForm) then + LFormClass := TCommonCustomFormClass(DelphiObjectClass); + //if we have a subclass of our Form wrapper, then check if we can find a //Delphi class that would have the same name as the Python class. //This would allow Python to instanciate an existing Delphi form class, @@ -176,12 +183,12 @@ TCommonCustomFormClass = class of TCommonCustomForm; LClass := GetClass('T' + LClassName); if Assigned(LClass) and LClass.InheritsFrom(TCommonCustomForm) then LFormClass := TCommonCustomFormClass(LClass); - end else begin - //get de default form class - if DelphiObjectClass.InheritsFrom(TCommonCustomForm) then - LFormClass := TCommonCustomFormClass(DelphiObjectClass); end; + if not Assigned(LFormClass) then + raise EInvalidFormClass.CreateFmt('Type %s is not a valid form class', [ + DelphiObjectClass.ClassName]); + //if it's not a design form, so we create it as a non-resourced form, //using the non-resourced constructor. //if the Owner is TApplication, then we have to call its CreateForm method, From bb0dd39c9e9b6d7db103812b5bfe4ce4e14bb4c3 Mon Sep 17 00:00:00 2001 From: Lucas Moura Belo Date: Tue, 22 Dec 2020 17:41:30 -0300 Subject: [PATCH 4/4] FMX form demo --- Demos/FMX/FormDemo/FormDemo.dpr | 15 + Demos/FMX/FormDemo/FormDemo.dproj | 976 ++++++++++++++++++++++++++++++ Demos/FMX/FormDemo/MainForm.fmx | 153 +++++ Demos/FMX/FormDemo/MainForm.pas | 63 ++ Demos/FMX/FormDemo/SecondForm.fmx | 31 + Demos/FMX/FormDemo/SecondForm.pas | 29 + 6 files changed, 1267 insertions(+) create mode 100644 Demos/FMX/FormDemo/FormDemo.dpr create mode 100644 Demos/FMX/FormDemo/FormDemo.dproj create mode 100644 Demos/FMX/FormDemo/MainForm.fmx create mode 100644 Demos/FMX/FormDemo/MainForm.pas create mode 100644 Demos/FMX/FormDemo/SecondForm.fmx create mode 100644 Demos/FMX/FormDemo/SecondForm.pas diff --git a/Demos/FMX/FormDemo/FormDemo.dpr b/Demos/FMX/FormDemo/FormDemo.dpr new file mode 100644 index 00000000..5cd27c59 --- /dev/null +++ b/Demos/FMX/FormDemo/FormDemo.dpr @@ -0,0 +1,15 @@ +program FormDemo; + +uses + System.StartUpCopy, + FMX.Forms, + MainForm in 'MainForm.pas' {Form1}, + SecondForm in 'SecondForm.pas' {DelphiSecondForm}; + +{$R *.res} + +begin + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. diff --git a/Demos/FMX/FormDemo/FormDemo.dproj b/Demos/FMX/FormDemo/FormDemo.dproj new file mode 100644 index 00000000..e83c0f22 --- /dev/null +++ b/Demos/FMX/FormDemo/FormDemo.dproj @@ -0,0 +1,976 @@ + + + {1C2733B2-64A7-4C99-BBD6-00BD9304B46E} + 19.1 + FMX + True + Debug + Win64 + 3 + Application + FormDemo.dpr + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + $(BDS)\bin\delphi_PROJECTICON.ico + $(BDS)\bin\delphi_PROJECTICNS.icns + FormDemo + + + DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;bindcompvclsmp;emsclientfiredac;tethering;svnui;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;svn;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;FireDACIBDriver;fmxdae;vcledge;FireDACDBXDriver;dbexpress;IndyCore;vclx;Python;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;PythonVcl;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;PythonFmx;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + $(BDS)\bin\default_app.manifest + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DBXSqliteDriver;RESTComponents;fmxase;DBXDb2Driver;DBXInterBaseDriver;vclactnband;vclFireDAC;bindcompvclsmp;emsclientfiredac;tethering;DataSnapFireDAC;FireDACADSDriver;DBXMSSQLDriver;DatasnapConnectorsFreePascal;FireDACMSSQLDriver;vcltouch;vcldb;bindcompfmx;DBXOracleDriver;inetdb;FmxTeeUI;emsedge;fmx;FireDACIBDriver;fmxdae;vcledge;FireDACDBXDriver;dbexpress;IndyCore;vclx;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;DataSnapConnectors;VCLRESTComponents;soapserver;vclie;bindengine;DBXMySQLDriver;CloudService;FireDACOracleDriver;FireDACMySQLDriver;DBXFirebirdDriver;FireDACCommonODBC;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;vcl;IndyIPServer;DBXSybaseASEDriver;IndySystem;FireDACDb2Driver;dsnapcon;FireDACMSAccDriver;fmxFireDAC;FireDACInfxDriver;vclimg;TeeDB;FireDAC;emshosting;FireDACSqliteDriver;FireDACPgDriver;FireDACASADriver;DBXOdbcDriver;FireDACTDataDriver;FMXTee;soaprtl;DbxCommonDriver;Tee;DataSnapServer;xmlrtl;soapmidas;DataSnapNativeClient;fmxobj;vclwinx;FireDACDSDriver;rtl;emsserverresource;DbxClientDriver;DBXSybaseASADriver;CustomIPTransport;vcldsnap;bindcomp;appanalytics;DBXInformixDriver;IndyIPClient;bindcompvcl;TeeUI;dbxcds;VclSmp;adortl;FireDACODBCDriver;DataSnapIndy10ServerTransport;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;inetdbxpress;FireDACMongoDBDriver;DataSnapServerMidas;$(DCC_UsePackage) + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + $(BDS)\bin\default_app.manifest + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png + $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + PerMonitorV2 + + + true + PerMonitorV2 + true + 1033 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + PerMonitorV2 + + + true + PerMonitorV2 + + + + MainSource + + +
Form1
+ fmx +
+ +
DelphiSecondForm
+ fmx +
+ + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Application + + + + FormDemo.dpr + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + FormDemo.rsm + true + + + + + true + + + + + true + + + + + FormDemo.exe + true + + + + + FormDemo.exe + true + + + + + FormDemo.exe + true + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + Contents\MacOS + 1 + .framework + + + Contents\MacOS + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + Contents\MacOS + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + Contents\Resources\StartUp\ + 0 + + + Contents\Resources\StartUp\ + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).launchscreen + 64 + + + ..\$(PROJECTNAME).launchscreen + 64 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + ..\ + 1 + + + ..\ + 1 + + + + + Contents + 1 + + + Contents + 1 + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + Contents\MacOS + 1 + + + Contents\MacOS + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + True + + + 12 + + + + +
diff --git a/Demos/FMX/FormDemo/MainForm.fmx b/Demos/FMX/FormDemo/MainForm.fmx new file mode 100644 index 00000000..2dd3dcb4 --- /dev/null +++ b/Demos/FMX/FormDemo/MainForm.fmx @@ -0,0 +1,153 @@ +object Form1: TForm1 + Left = 0 + Top = 0 + Caption = 'MainForm' + ClientHeight = 480 + ClientWidth = 640 + FormFactor.Width = 320 + FormFactor.Height = 480 + FormFactor.Devices = [Desktop] + DesignerMasterStyle = 0 + object OpenDialog1: TOpenDialog + DefaultExt = '*.py' + Filter = 'Python files|*.py|Text files|*.txt|All files|*.*' + Left = 200 + end + object SaveDialog1: TSaveDialog + DefaultExt = '*.py' + Filter = 'Python files|*.py|Text files|*.txt|All files|*.*' + Left = 232 + end + object Memo1: TMemo + Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] + DataDetectorTypes = [] + Align = Top + Size.Width = 640.000000000000000000 + Size.Height = 200.000000000000000000 + Size.PlatformDefault = False + TabOrder = 8 + Viewport.Width = 636.000000000000000000 + Viewport.Height = 196.000000000000000000 + end + object Splitter1: TSplitter + Align = Top + Cursor = crVSplit + MinSize = 20.000000000000000000 + Position.Y = 200.000000000000000000 + Size.Width = 640.000000000000000000 + Size.Height = 3.000000000000000000 + Size.PlatformDefault = False + end + object Memo2: TMemo + Touch.InteractiveGestures = [Pan, LongTap, DoubleTap] + DataDetectorTypes = [] + Lines.Strings = ( + 'from spam import Form' + '' + 'class SubForm(Form): ' + ' def __init__(self, Owner):' + ' self.Caption = '#39'Subclassed form defined in Python'#39 + '' + 'class DelphiSecondForm(Form):' + ' pass' + '' + 'def createbaseform():' + ' print('#39'Creates a Delphi FMX.TForm'#39')' + ' form = Form(None)' + ' try:' + ' form.Caption = "Delphi FMX base form"' + ' form.ShowModal()' + ' finally:' + ' form.Free();' + '' + 'def createpysubform():' + ' print('#39'Creates a Delphi FMX.TForm subtype defined in Python'#39')' + ' form = SubForm(None)' + ' try:' + ' form.ShowModal()' + ' finally:' + ' form.Free()' + '' + 'def createdelphisubform():' + + ' print('#39'Creates an instance of TDelphiSecondForm registerd form' + + #39')' + ' form = DelphiSecondForm(None)' + ' try:' + ' print('#39'Label: '#39', form.Label1.Text)' + ' form.ShowModal()' + ' finally:' + ' form.Free()' + '' + 'def main():' + ' createbaseform()' + ' createpysubform()' + ' createdelphisubform()' + '' + 'if __name__ == '#39'__main__'#39':' + ' try:' + ' main()' + ' except SystemExit:' + ' pass') + Align = Client + Size.Width = 640.000000000000000000 + Size.Height = 232.000000000000000000 + Size.PlatformDefault = False + TabOrder = 10 + Viewport.Width = 620.000000000000000000 + Viewport.Height = 228.000000000000000000 + end + object Panel1: TPanel + Align = Bottom + Position.Y = 435.000000000000000000 + Size.Width = 640.000000000000000000 + Size.Height = 45.000000000000000000 + Size.PlatformDefault = False + TabOrder = 11 + object Button1: TButton + Position.X = 8.000000000000000000 + Position.Y = 10.000000000000000000 + Size.Width = 97.000000000000000000 + Size.Height = 22.000000000000000000 + Size.PlatformDefault = False + TabOrder = 2 + Text = 'Execute script' + OnClick = Button1Click + end + object Button2: TButton + Position.X = 192.000000000000000000 + Position.Y = 10.000000000000000000 + TabOrder = 1 + Text = 'Load script...' + OnClick = Button2Click + end + object Button3: TButton + Position.X = 280.000000000000000000 + Position.Y = 10.000000000000000000 + TabOrder = 0 + Text = 'Save script...' + OnClick = Button3Click + end + end + object PythonEngine1: TPythonEngine + IO = PythonGUIInputOutput1 + Left = 8 + end + object PythonModule1: TPythonModule + Engine = PythonEngine1 + ModuleName = 'spam' + Errors = <> + Left = 40 + end + object PythonGUIInputOutput1: TPythonGUIInputOutput + UnicodeIO = True + RawOutput = False + Output = Memo1 + Left = 104 + end + object PyDelphiWrapper1: TPyDelphiWrapper + Engine = PythonEngine1 + Module = PythonModule1 + Left = 72 + end +end diff --git a/Demos/FMX/FormDemo/MainForm.pas b/Demos/FMX/FormDemo/MainForm.pas new file mode 100644 index 00000000..3f9768ca --- /dev/null +++ b/Demos/FMX/FormDemo/MainForm.pas @@ -0,0 +1,63 @@ +unit MainForm; + +interface + +uses + System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, + FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types, + FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo, + PythonEngine, WrapDelphi, FMX.PythonGUIInputOutput, WrapDelphiFmx; + +type + TForm1 = class(TForm) + OpenDialog1: TOpenDialog; + SaveDialog1: TSaveDialog; + Memo1: TMemo; + Splitter1: TSplitter; + Memo2: TMemo; + Panel1: TPanel; + Button1: TButton; + Button2: TButton; + Button3: TButton; + PythonEngine1: TPythonEngine; + PythonModule1: TPythonModule; + PythonGUIInputOutput1: TPythonGUIInputOutput; + PyDelphiWrapper1: TPyDelphiWrapper; + procedure Button2Click(Sender: TObject); + procedure Button3Click(Sender: TObject); + procedure Button1Click(Sender: TObject); + private + { Private declarations } + public + { Public declarations } + end; + +var + Form1: TForm1; + +implementation + +{$R *.fmx} + +procedure TForm1.Button1Click(Sender: TObject); +begin + PythonEngine1.ExecStrings(Memo2.Lines); +end; + +procedure TForm1.Button2Click(Sender: TObject); +begin + with OpenDialog1 do begin + if Execute then + Memo2.Lines.LoadFromFile( FileName ); + end; +end; + +procedure TForm1.Button3Click(Sender: TObject); +begin + with SaveDialog1 do begin + if Execute then + Memo2.Lines.SaveToFile(FileName); + end; +end; + +end. diff --git a/Demos/FMX/FormDemo/SecondForm.fmx b/Demos/FMX/FormDemo/SecondForm.fmx new file mode 100644 index 00000000..b18c8f4d --- /dev/null +++ b/Demos/FMX/FormDemo/SecondForm.fmx @@ -0,0 +1,31 @@ +object DelphiSecondForm: TDelphiSecondForm + Left = 0 + Top = 0 + Caption = 'Delphi second form' + ClientHeight = 480 + ClientWidth = 640 + FormFactor.Width = 320 + FormFactor.Height = 480 + FormFactor.Devices = [Desktop] + DesignerMasterStyle = 0 + object Label1: TLabel + Align = Top + AutoSize = True + StyledSettings = [Family, FontColor] + Margins.Left = 10.000000000000000000 + Margins.Top = 10.000000000000000000 + Margins.Right = 10.000000000000000000 + Margins.Bottom = 10.000000000000000000 + Position.X = 10.000000000000000000 + Position.Y = 10.000000000000000000 + Size.Width = 620.000000000000000000 + Size.Height = 30.000000000000000000 + Size.PlatformDefault = False + StyleLookup = 'labelstyle' + TextSettings.Font.Size = 22.000000000000000000 + TextSettings.Font.StyleExt = {00070000000000000004000000} + TextSettings.HorzAlign = Center + Text = 'This is a Delphi registerd form' + TabOrder = 1 + end +end diff --git a/Demos/FMX/FormDemo/SecondForm.pas b/Demos/FMX/FormDemo/SecondForm.pas new file mode 100644 index 00000000..732d0fcf --- /dev/null +++ b/Demos/FMX/FormDemo/SecondForm.pas @@ -0,0 +1,29 @@ +unit SecondForm; + +interface + +uses + System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, + FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, + FMX.Controls.Presentation, FMX.StdCtrls; + +type + TDelphiSecondForm = class(TForm) + Label1: TLabel; + private + { Private declarations } + public + { Public declarations } + end; + +var + DelphiSecondForm: TDelphiSecondForm; + +implementation + +{$R *.fmx} + +initialization + RegisterClass(TDelphiSecondForm); + +end.