Girish Patil 3 Posted April 3, 2020 Hi, I’m checking to see if there are better ways to have a common codebase for both VCL and FMX components. Here’s some information on the scenario and the current implementation: We are working on having a common code base for the Document Printer component in Document Studio. Only about 10-15 lines of code are platform (OS) and framework (VCL/FMX) specific. The VCL component needs to link to/use VCL units - Printer, Graphics, etc., and likewise the FMX version needs to link to/use FMX units - Printer, Graphics… Since the controls link to different frameworks and their respective units and since they need to be installed on the component palette, the unit that contains the control needs to be different for each framework (VCL, FMX). And It’s organised in the following way currently: Unit vclgtDocumentPrinter {$Define gtVCL} {$Include gtDocumentPrinter.inc} // this file has all the code … Unit FMX.gtDocumentPrinter {$Define gtFMX} {$Include gtDocumentPrinter.inc} // this file has all the code … There’s one apparent issue with this way: code completion doesn’t work in the inc file. Are there better ways of having a common code base for controls in the scenario explained above? Thank you, -- Girish PatilGnosticewww.gnostice.com Share this post Link to post
ConstantGardener 31 Posted April 3, 2020 I am far from being an expert, but is'nt this https://www.tmssoftware.com/site/fncpartners.asp a way to archive this? Share this post Link to post
vfbb 285 Posted April 3, 2020 (edited) I suggest you to create 2 different packages, with the same units, but need to have 2 different packages, one for FMX and one for VCL. After create packages, add in the project options of each package, in the "Conditional defines" something like USING_VCL for the vcl package and USING_FMX for the fmx package.In code of your .pas just use: {$IFDEF USING_VCL} ... {$ENDIF} or {$IFDEF USING_FMX} ... {$ENDIF} Edited April 4, 2020 by vfbb 1 Share this post Link to post
Remy Lebeau 1396 Posted April 4, 2020 6 hours ago, Girish Patil said: I’m checking to see if there are better ways to have a common codebase for both VCL and FMX components. Is your component visual (derived from TControl)? Or is it non-visual (derived from TComponent)? Non-visual components can be used in both VCL and FMX without splitting up the implementation (just IFDEF the pieces you need). But visual controls take more work to design for separate frameworks. 6 hours ago, Girish Patil said: Only about 10-15 lines of code are platform (OS) and framework (VCL/FMX) specific. Then those lines should be in separate units. The rest of your code should be in a common unit(s) that the framework-specific units can then use. 6 hours ago, Girish Patil said: The VCL component needs to link to/use VCL units - Printer, Graphics, etc., and likewise the FMX version needs to link to/use FMX units - Printer, Graphics… This is where Unit Scope Names come into play. Create separate VCL-specific and FMX-specific projects with appropriate Unit Scope Names specified in the Project Options, and then don't use any Unit Scope names in your code. That way, you have less IFDEF'ing to do. 6 hours ago, Girish Patil said: Since the controls link to different frameworks and their respective units and since they need to be installed on the component palette, the unit that contains the control needs to be different for each framework (VCL, FMX). And It’s organised in the following way currently: Unit vclgtDocumentPrinter {$Define gtVCL} {$Include gtDocumentPrinter.inc} // this file has all the code … Unit FMX.gtDocumentPrinter {$Define gtFMX} {$Include gtDocumentPrinter.inc} // this file has all the code … Your common gtDocumentPrinter code should be in its own separate unit, not in an include file. 6 hours ago, Girish Patil said: There’s one apparent issue with this way: code completion doesn’t work in the inc file. All the more reason not to use an include file. 2 Share this post Link to post
Fr0sT.Brutal 900 Posted April 4, 2020 The simplest solution is like ICS team did. Create usual VCL unit with some IFDEFs disabling unit-specific lines when UseFMX is defined and a thin wrapper for FMX that includes VCL unit like an inc Share this post Link to post
Girish Patil 3 Posted April 6, 2020 (edited) Thanks to all who replied. I was looking into the details, the code base side-by-side with the suggestions. On 4/4/2020 at 7:15 AM, Remy Lebeau said: Is your component visual (derived from TControl)? Or is it non-visual (derived from TComponent)? Non-visual components can be used in both VCL and FMX without splitting up the implementation (just IFDEF the pieces you need). I/we were aware of this and the unit scoping, and have gone this way with some components before, but it had started out being separate units so continued to go that way. And then again, I paused to see if there was a better way to go 🙂 We've gone with the separate packages, unit scoping, and same unit approach. Will need to do some package reorganization and some code reorganisation, but it will definitely make things cleaner. So, might as well do it! We will have dialogs for the components and that will be very platform specific and linking to the visual classes/units of the frameworks, but that can be separated out in one of the suggested ways. Thanks. Edited April 6, 2020 by Girish Patil Share this post Link to post
Girish Patil 3 Posted April 6, 2020 On 4/4/2020 at 4:10 PM, Fr0sT.Brutal said: The simplest solution is like ICS team did. Create usual VCL unit with some IFDEFs disabling unit-specific lines when UseFMX is defined and a thin wrapper for FMX that includes VCL unit like an inc This is also useful. Thanks. Share this post Link to post