Delphi tools - Name property editorGeplaatst door Baldo op 06-04-03Erik 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.
|