Delphi tools: Name property editor
Erik Stok (aka Baldo)
Delphi's open tools api (OTA) biedt geweldige mogelijkheden om
de IDE uit te breiden met handigheden van jezelf. Er is veel over
de OTA te vinden op het web, maar veel artikelen vertellen vooral
wat er kan en verzuimen een praktisch toepasbaar voorbeeld te geven
van het gebruik van de OTA. NLDelphi is een plaats die draait om
Delphi in de praktijk, dus een betere plaats om de praktische kan
van de OTA te beschrijven kan ik me niet indenken. Dit eerste artikel
beschrijft het bouwen van een property editor.
Het idee
Een van de eerste uitbreidingen die ik op Delphi maakte was een
property editor om de naam van componenten snel in te kunnen vullen.
Ik wil namelijk wel componenten een nette naam geven, maar niet
heen en weer klikken en tweemaal gegevens intoetsen. Het viel me
namelijk op dat ik bijvoorbeeld bij het plaatsen van een button
op een form allereerst de caption property zette (bijvoorbeeld op
'Sluiten') waarna ik de naam van de button op praktisch hetzelfde
zet (in dit voorbeeld op 'btnSluiten'). Het werken met prefix of
suffix maakt natuurlijk voor het patroon van handelingen geen verschil.
Het eerste wat ik wilde doen was ervoor zorgen dat ik voor dezelfde
componenten in ieder geval dezelfde prefix zou gebruiken. Het volgende
doel was het gebruiken van bepaalde properties van het component
om de naam samen te stellen.
Het meest gemakkelijk leek mij een dubbelklik op de naam van het
component waarna de prefix zou zijn ingevuld voor het betreffende
component. Een property editor lag voor de hand dus. In dit artikel
zal ik de bouw van deze property editor behandelen.
De benodigdheden zijn dus: een property editor die voor het betreffende
component de juiste prefix toont en een lijst met prefixen voor
alle bekende componenten.
De lijst met bekende prefixen samenstellen is echter een hele klus.
En als ik een nieuwe componentenbibliotheek installeer dan moet
de lijst weer aangevuld worden. En wat als ik een component nooit
gebruikt? Dan ga ik voor niets een prefix bedenken. De oplossing
is eenvoudig. De property editor toont een combobox met één
of twee opties: als eerste de prefix van het component als die bekend
is en als tweede de optie om de lijst met prefixen te onderhouden.
Een dubbelklik op de name property zal dan leiden tot het invullen
van de prefix en als deze niet bekend is wordt automatisch het prefix
onderhoud gestart.
Property editors
In de DesignEditors unit (terug te vinden in de Delphi map onder
Source\ToolsAPI) zit een class genaamd TPropertyEditor. Door een
afgeleide van deze class te maken en bepaalde methods te overriden
is het eenvoudig een eigen property editor te maken. Als in de Delphi
help gezocht wordt op TPropertyEditor dan staat vrij expliciet uitgelegd
wat de TPropertyEditor allemaal kan. Ik ga hier dan ook niet verder
in op de details van TPropertyEditor, behalve die details die noodzakelijk
zijn om de name property editor te bouwen.
Het zal geen verassing zijn dat de class definition voor de name
property editor er als volgt uitziet:
TNamePropertyEditor = class(TPropertyEditor)
protected function FirstComponent: TComponent; virtual; function PrefixClassName: String; virtual;
function ReadPrefixFromIniFile: String; procedure WritePrefixToIniFile(Prefix: String); public function GetAttributes: TPropertyAttributes; override; function GetValue: String; override; procedure SetValue(const Value: String); override; procedure GetValues(Proc: TGetStrProc); override; end;
Via de GetAttributes method kunnen we aangeven waartoe deze
property editor allemaal in staat is. In dit geval is een combobox
gewenst, dus het resultaat van deze method is de paValueList
optie.
Bij een combobox implementatie geldt dat de GetValue method
de huidige waarde teruggeeft, dat de SetValue method de nieuw
geselecteerde waarde zet en dat de GetValues method een lijst
van mogelijk te selecteren waarden geeft.
Bij de GetValue method zal dus altijd de waarde van de name
property teruggegeven worden als resultaat.
De SetValue method zal twee dingen moeten kunnen. Enerzijds
zal de geselecteerde prefix als nieuwe waarde van de name property
gezet moeten kunnen worden. Anderzijds zal er bij het selecteren
van de optie 'onderhoud prefixen' het scherm voor het onderhoud
van de prefixen moeten worden gestart.
De GetValues method zal een lijst terug moeten geven met
één of twee items. De optie 'onderhoud prefixen' en
eventueel de prefix die voor dit component bekend is.
De protected methods zijn ondersteunende methods. FirstComponent
helpt om eenvoudig het component te bepalen waarvan momenteel
de name property wordt bewerkt. De PrefixClassName method
geeft de naam van de class van het component.
Onderhoud op de lijst
De lijst van bekende prefixen is een eenvoudige lijst. Door bij
te houden van elke componentclass wat de bijbehorende prefix is
kan per component een prefix worden getoond. Deze lijst kan bijvoorbeeld
worden opgeslagen in een .ini bestand. Het bestand kan de volgende
structuur hebben:
[Prefixes]
TButton=btn
TPanel=pnl
TDataSource=dts
De method ReadPrefixFromIniFile leest een prefix uit het
ini bestand met de bovengenoemde structuur. WritePrefixToIniFile
schrijft een prefix naar hetzelfde ini bestand.
Het onderhoud op deze lijst is geïmplementeerd met behulp
van een InputQuery dialog. Natuurlijk kan hiervoor een veel meer
elegante oplossing gekozen worden, maar voor dit artikel is het
voldoende.
Speciale componenten
Er zijn wat speciale gevallen waarin de name property editor zich
anders moet gedragen. De prefix van een form is namelijk niet te
bepalen, omdat de classname van het 'component' per form verschilt.
Om toch voor ieder form dezelfde prefix te kunnen hanteren, wordt
gekeken naar de owner van het component. Als de prefix moet worden
bepaald van een component zonder owner, dan wordt veronderstelt
dat dit een TForm afgeleide is.
Voor datamodules geldt hetzelfde als voor forms. Een datamodule
heeft echter wél een owner. Dit is of een TDataModuleForm
of een TDataModuleDesigner.
Registratie
Een essentieel onderdeel bij de bouw van een property editor is
de registratie. Net als bij het bouwen van eigen componenten die
in de IDE worden geregistreerd, moet ook bij property editors de
Register procedure worden geïmplementeerd. En ook hier geldt
dat de naam van deze procedure hoofdlettergevoelig is.
Bij registratie wordt gebruik gemaakt van de RegisterPropertyEditor
procedure. Hierbij dient te worden opgegeven wat de type informatie
is van de property waarvoor de editor geschreven is. In dit geval
is het een property van het type TComponentName, dus daarvan
wordt de type informatie doorgegeven. Tevens moet worden aangegeven
voor welke componentclass de property editor bedoeld is. In ons
geval is de editor voor elke TComponent descendant bedoeld.
De volgende parameter is de naam van de property die het betreft:
in ons geval dus 'Name'. Als laatste parameter wordt de property
editor zelf doorgegeven.
De simpele versie
De simpele versie van de name property editor is nu klaar. De editor
kan voor ieder component een prefix registreren en voor bekende
componenten kan de prefix worden geselecteerd uit de lijst van prefixen.
Het package waarin de broncode
staat voor de simpele versie van de property editor kan worden geïnstalleerd
net als ieder ander designtime package. Let op: de editor is niet
perfect, want allerlei controles op geldigheid van de prefix en
dergelijke worden nog niet gedaan.
Prefix formules
De volgende stap is het toevoegen van de waarde van een property
in de naam van het component. De meest eenvoudige oplossing is het
maken van een formule voor een prefix en een property waarde. De
mogelijkheid wordt toegevoegd om een + symbool te gebruiken in de
opgegeven prefix, waarna de naam van een string property volgt.
De inhoud van het ini bestand zou er dan als volgt uit kunnen zien:
[Prefixes]
TButton=btn+Caption
TPanel=pnl+Caption
TDataSource=dts
De property editor kan worden uitgebreid met twee methods: EvaluatePrefix
en StripInvalidChars. De eerste evalueert de prefix tot een
prefix en eventuele waarde van een string property, de tweede zorgt
dat de waarde van de string property alle geldige tekens bevat voor
het benamen van een component.
Om de string property uit te lezen wordt gebruik gemaakt van de
unit typinfo (terug te vinden in de Delphi map onder Source\Rtl\Common).
De functies IsPublishedProp wordt gebruikt om te controleren
of de property die is opgegeven ook een geldige published property
van het component is. De functie GetStrProp wordt gebruikt
om de waarde van de property op te halen.
De complete versie
De complete versie van de name property editor is nu klaar. De
editor kan voor ieder component een prefix formule registreren en
voor bekende componenten kan de prefix worden geselecteerd uit de
lijst van prefixen. Het package
waarin de broncode staat voor de complete versie van de property
editor kan worden geïnstalleerd net als ieder ander designtime
package. Let op: ook deze editor is niet perfect, want allerlei
controles worden nog niet gedaan.
Conclusie
Het is duidelijk dat de Delphi open tools api op eenvoudige wijze
toestaat handige IDE extensies te maken die het leven vereenvoudigen.
En het mooiste is: alles kan worden geprogrammeerd in de bekende
Delphi syntax. De name property editor is een voorbeeld hiervan
dat menige ontwikkelaar zal aanspreken vanwege zijn eenvoud en toepasbaarheid.
|