Allow to adjust the units/packages that are added when dropping a component on a form
Original Reporter info from Mantis: PascalDragon @PascalDragon
-
Reporter name: Sven Barth
Original Reporter info from Mantis: PascalDragon @PascalDragon
- Reporter name: Sven Barth
Description:
Sometimes it would be good to allow for a component to adjust the units/packages that are added to the form's/frame's unit or the project when a component is dropped on the form. For example Indy or DevExpress components make use of this in Delphi to add additional units to the uses clause that are more often than not required to use the component correctly.
The need to specifiy the package or to provide an additional package dependency is less often needed than the unit one, but I /do/ have a use case for that. Namely the Pas2JS Widgets project ( https://github.com/pascaldragon/Pas2JS_Widget ) which uses the IDE's designer to provide the components. Currently it adds the design time package, but the Pas2JS specific package is needed instead.
In Delphi this is functionality implemented by SelectionEditors, however in my opinion that doesn't feel very logical as SelectionEditors apply to the selection of existing components on the form, not to mention that they require the designer as a dependency.
Thus I implemented this as a separate class that can be registered in a design time package:
=== code begin ===
TBaseComponentRequirements = class
public
constructor Create({%H-}ComponentClass: TComponentClass); virtual;
procedure RequiredUnits(Units: TStrings); virtual; abstract;
procedure RequiredPkgs(Pkgs: TStrings); virtual; abstract;
end;
=== code end ===
As can be seen this class only depends on the class of the component (thus no instance required yet). The Required* methods get the default unit/package passed in and the class can either extend that or completely replace it.
A TComponentRequirements descendant is provided as well so that not both methods need to be overridden if a class only needs to adjust the units.
Additional information:
componenteditors.patch:
This patch implements the TComponentRequirements in the ComponentEditors unit. This could be added to a separate unit as well if desired.
pkgmanager.patch:
The TPkgManager.AddUnitDependenciesForComponentClasses is the main work horse for adding units/packages to the form's unit/project. This patch not only implements the functionality required for the component requirements, but it also cleans things up a bit:
- AddUnitDependenciesForComponentClasses enumerates the classes twice, once in CollectNeededUnitsAndPackages and once in GetMissingDependenciesForUnit
- the packages collected in CollectNeededUnitsAndPackages are not used anywhere
- GetMissingDependenciesForUnit retrieves the packages for a component for each unit owner while this doesn't depend on the unit owner at all
Thus the patch moves the work to retrieve the units and packages for an array of components to new method GetUnitsAndDependenciesForComponents. The package list is then filtered by FilterMissingDependenciesForUnit. Both methods are still used by the backwards compatible GetMissingDependenciesForUnit. Also the no longer required CollectNeededUnitsAndPackages is removed.
It is also GetUnitsAndDependenciesForComponents that uses the component requirements.
What could be further improved is to move the search for the packages to the TPackageGraph class (this needs to be done this way as the package might not be an installed one).