|
RiverSoftAVG Newsletter #9
July/Aug/Sep 2002 Hello and welcome back for the 9th edition of the RiverSoftAVG newsletter! It has been a busy but satisfying summer - the release of the Inference Engine Component Suite v2.0 in July was a landmark for us. We hope that everyone has had as good a few months.
The major article in this issue is about a free download with source available
from our website, the New Collection Wizard, usable by any of our customers.
There is also a great tip for IECS v2.0 users, for creating a case-insensitive
version of the InferenceEngine. Finally, there are a couple of news items and
downloads we want you to know about.
A reminder, this newsletter and all previous ones are available for download from the web site at http://www.riversoftavg.com/articles_&_tips.htm Contents Article: Using the New Collection Wizard
News: IECS v2.01 has been released
News: RiverSoftAVG's IECS available on the Delphi 7 Companion CD
Tip: Making the IECS v2.0 case-insensitive
Download: New IECS Help files (for version 1 and 2) are available Note: You received this newsletter because you are an owner of a RiverSoftAVG product. If you received this newsletter by mistake or if for any reason you wish to not receive any future mailings from RiverSoftAVG, just reply to this message informing us so. We apologize for any intrusion. Article: Using the New Collection Wizard For component writers, Delphi's TCollection class is a well-designed and time-saving list/collection class. Though it is not the fastest list object, component writers descending from this class get automatic support for their list/collection object in the IDE, automatic support for assignment statements, and well designed collection-manipulation methods. However, programming a new collection class can be tedious: you need to fill in the collection item's assign method and, even worse, override many methods in the TCollection to typecast your new collection item type. You find yourself writing many little routines like this:
function TMyCollection.Add:
TMyCollectionItem;
begin result := TMyCollectionItem(inherited Add); end;
We have created a handy little wizard for Delphi to take the drudgery out of
coding TCollection descendants, available from the website at
www.RiverSoftAVG.com/downloads.htm This article explains how to install
and use this New Collection Wizard to quickly and safely create TCollection
and TCollectionItem descendants. Note that this wizard can be used in
Standard, Professional, or Enterprise versions of Delphi. Also, note that
this article assumes some familiarity with programming components.
How to install the New Collection Wizard
1. Unzip the file into any directory.
2. Start Delphi. Open the CommonWizards.dpk package
3. This package requires the PasLexD60 package (a freeware Pascal Parser/Lexer,
also available from our download package). If you are using Delphi 5, you
need to remove PasLexD60 from the package and add the correct version of the
PasLex package
3. Compile and Install the package
4. That's it! You're done. The New Collection Wizard is now available from
the File->New->Other... window in the "New" tab sheet.
Ok, now that it is installed, let's use it. The New Collection Wizard adds
the source code it generates to the current file you are editing. To keep
this tutorial as straightforward as possible, let's create a new unit and work
in that. First, create the unit (File->New...->Unit). Now, start the wizard
by opening the New Collection Wizard in the File->New...->Other... New tab
sheet. You should see a window appear titled "New Collection Wizard". There
are 4 edit boxes/combo boxes at the top, a 3 tab page control in the middle,
and Ok/Cancel buttons at the bottom.
The 3 tab sheets in the middle specify Options, Collection Item properties,
and a Preview. We will discuss the Options and Collection Items Properites in
a moment, but the preview tab is especially useful. This tab shows you the
code that the New Collection Wizard will generate based on your inputs and
options. The easiest way to understand the different edit boxes and options
of the wizard is to experiment and then check the code in the Preview pane.
The 4 edit boxes are where you specify the name of the collection and the
collection item, what class the collection descends from, and the owner of the
collection. So, for example, if you wanted to define a TMyCollection =
class(TOwnedCollection), which has TMyCollectionItem items and whose owner is
TMyComponent, you would fill in TMyCollectionItem, TMyCollection,
TOwnedCollection, and TMyComponent from top to bottom in each of the edit
boxes.
The Options tab sheet in the middle of the wizard controls what source code is
generated. The first two Options specify if you want the TCollectionItem
and/or the TCollection class to be generated. The rest of the options control
what parts of the TCollectionItem or TCollection class code is generated.
Checking "Add Collection Reference to Owned Collection Item" generates code in
the collection item to correctly reference the Owning Collection by the new
TCollection type, e.g.,
property Collection:
TMyCollection read GetCollection write
SetCollection;
The "Add Owner Reference to Owned Collection" check box serves the same
purpose for the TCollection descendant to reference the owning component,
e.g.,
function Owner:
TMyComponent; reintroduce;
The "Add "Safe" Constructor" check box controls whether a new constructor
should be generated for the TCollection descendant which hides the
TCollectionItems created and doesn't allow it to be changed. Both the
TCollection and TOwnedCollection classes define constructors which allow you
to pass in the TCollectionItemClass it should create. By checking this box,
the wizard generates a new constructor which only allows passing in the Owner
to the collection, e.g.,
constructor Create(AOwner:
TMyComponent);
When the "Add Assign Method to Collection Item" check box is checked, the
wizard overrides the Assign method for the TCollectionItem and puts in code
for assigning the properties of the collection item, e.g,
procedure
TMyCollectionItem.Assign(Source: TPersistent);
begin if Source is TMyCollectionItem then begin // Copy properties here FName := TMyCollectionItem(Source).Name; FSize := TMyCollectionItem(Source).Size; Changed(False); end else inherited Assign(Source); end;
Finally, the "Override GetDisplayName method in Collection Item" check box
controls whether the wizard generates code for the collection item to retrieve
a different DisplayName than the default. If this check box is checked, the
wizard generates the overridden method and puts a TODO in the code for you so
that you know to put the proper code in, e.g.,
function
TMyCollectionItem.GetDisplayName: String;
begin result := ''; {TODO: Update code for Display Name based on your properties} if result = '' then result := inherited GetDisplayName; end;
The Collection Item Properties tab sheet allows you to enter properties for
your collection item. The wizard allows you to define the property name and
type, private field, and optional read and write accessor methods. The wizard
will take care of writing all the code for you, including calling the Changed
method for the SetProperty method and copying the property in the Assign
method.
There are some limitations to the New Collection Wizard:
While there are significant limitations, this wizard is a powerful way to
create collections quickly and safely. Already, this wizard has had an impact
in our code development. The quick generation of code for the properties
alone makes this wizard invaluable. We hope you will find this wizard just as
useful to you in your development.
News: IECS v2.01 has been released We have just made a small, but very important, update to the IECS v2.0. The new version, IECS v2.01, rolls in the bug fix at v2.0's release with some important new features:
An evaluation version of the IECS v2.01 is available directly at our website
at
www.RiverSoftAVG.com/downloads.htm or from Borland's Code Central at
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=18413
News: RiverSoftAVG's IECS available on the Delphi 7 Companion CD
RiverSoftAVG is proud to announce that an evaluation version of its latest
flagship product, the Inference Engine Component Suite v2.0, will be shipping
on Delphi 7's Companion CD. The version that will be on the Companion CD
(v2.0), can also be downloaded from Code Central at
http://codecentral.borland.com/codecentral/ccweb.exe/listing?id=18413
Tip: Making the IECS v2.0 case-insensitive
The new IECS v2.0 makes adding and modifying parsers incredibly easy. More
methods and variables are available to tweak the behavior of the parsers. In
addition, the IECS is more "parser-aware" and will use the new parsers even in
the editor dialogs. This tip shows how to create a new parser and use it in
the IECS to make the IECS syntax case-insensitive. Note: technically,
this tip does not make the IECS case insensitive. Rather, it transform the
inputs to lowercase. So, the user can write "DefRule MyName", "DEFRULE MYNAME",
or "dEfRuLe MyNaMe" and they all mean the same for the IECS, "defrule myname".
To make the IECS case-insensitive, we need to perform two functions: convert user input to one case (either Uppercase or Lowercase) and convert the internal variables and names used by the IECS to the same case. Since the IECS functions are all already lowercase, we are going to convert the user inputs to lowercase to save effort (though it is certainly possible to change all the function names).
First, create a new component in Delphi. The ancestor class will be
TInferenceEngine (or TDBInferenceEngine). For our example, we will call the
new component, TCIInferenceEngine (the CI stands for case insensitive).
Delphi will create the unit for us and make the class declaration:
TCIInferenceEngine = class(TInferenceEngine)
private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end;
To make the user input case-insensitive, it turns
out that we don't need to change the parser at all. Instead, we need to
change the tokenizer to change all parsed tokens to lowercase (except for
strings, we want to allow the user to specify case in strings). We need to
make a new class which descends from TIEClipsStream. The TIEClipsStream class
has a protected method, FinishToken, which is called whenever a token is
parsed. We override this method and convert the string input to lowercase
(you need to add IEInterfaces to the uses clause too):
TCIStream = class(TIEClipsStream)
private { Private declarations } protected { Protected declarations } function FinishToken(AChar: Integer; const AString: String): IStreamToken; override; public { Public declarations } published { Published declarations } end;
{ TCIStream }
function TCIStream.FinishToken(AChar: Integer;
const AString: String): IStreamToken; begin if AChar <> Ord('"') then result := inherited FinishToken(AChar, LowerCase(AString)) else result := inherited FinishToken(AChar, AString); end;
Our code above checks the AChar parameter, which
gives a hint about the token data type to create, to see if it is a string.
If it is not, it converts the AString input parameter to lowercase and calls
the inherited FinishToken method. Otherwise, if it is a string, we leave the
AString input parameter alone and call the inherited method.
Voila! We are done with the parsing and
tokenization. To make our new TInferenceEngine component USE the new
tokenizer, we set the TokenizerType property. For our purposes, we will set
the TokenizerType property in the TCIInferenceEngine constructor:
constructor TCIInferenceEngine.Create(AOwner: TComponent);
begin inherited Create( AOwner ); TokenizerType := TCIStream; end;
Ok, now we have finished the user input part of
our problem. To make sure the TInferenceEngine functions and variables match
the lowercase user-input, we need to set some global variables. We will
create an initialization section for the unit and set the
variables (note for the following code you need to add the IEConsts and
IEValue units to your uses clause):
initialization
SDefaultSlotName := LowerCase(SDefaultSlotName); SInitialFactPattern := LowerCase(SInitialFactPattern); SInitialFact := LowerCase(SInitialFact); SEmptyFuzzy := LowerCase(SEmptyFuzzy); SLocalBinding := LowerCase(SLocalBinding); SPatternBinding := LowerCase(SPatternBinding); SRuleBinding := LowerCase(SRuleBinding); SNULLFact := LowerCase(SNULLFact); STypeSymbolKeyword := LowerCase(STypeSymbolKeyword); STypeAtomKeyword := LowerCase(STypeAtomKeyword); STypeStringKeyword := LowerCase(STypeStringKeyword); STypeIntegerKeyword := LowerCase(STypeIntegerKeyword); STypeFloatKeyword := LowerCase(STypeFloatKeyword); STypeLexemeKeyword := LowerCase(STypeLexemeKeyword); STypeNumberKeyword := LowerCase(STypeNumberKeyword); STypeClassKeyword := LowerCase(STypeClassKeyword); STypeDescriptorKeyword := LowerCase(STypeDescriptorKeyword); STypeObjectKeyword := LowerCase(STypeObjectKeyword); STypeExternalAddrKeyword := LowerCase(STypeExternalAddrKeyword); STypeFuzzyKeyword := LowerCase(STypeFuzzyKeyword); STypeFactKeyword := LowerCase(STypeFactKeyword); STypeFactIdKeyword := LowerCase(STypeFactIdKeyword); STypeVariableKeyword := LowerCase(STypeVariableKeyword); FCTrue.AsAtom := 'true'; FCFalse.AsAtom := 'false'; FCEOF.AsAtom := 'eof';
Note that, in general, this new unit cannot
coexist with regular TInferenceEngine components because they use the same
global variables.
At this point, we are done. You can easily test
this component. Create a new application and form and add your component unit
to the uses clause. In the OnCreate event of the form, create the
TCIInferenceEngine component:
procedure TForm1.FormCreate(Sender: TObject);
begin CIInferenceEngine1 := TCIInferenceEngine.Create(Self); end;
Drop a button and a TConsoleDialog component on
the form. In the button's OnClick event, assign the CIInferenceEngine1
component to the console dialog's Engine property and execute it:
procedure TForm1.Button1Click(Sender: TObject);
begin ConsoleDialog1.Engine := CIInferenceEngine1; ConsoleDialog1.Execute; end;
Compile and run the application. Click the button
and play with the new case-insensitive inference engine!
Download: New IECS Help files (for version 1 and 2) are available
The IECS help files have been updated (for v1.11 and v2.0). The new files have "Hierarchy" pages for every class and sorted "See Also" pages. You can download the files at:
v1.11
Delphi 4:
www.RiverSoftAVG.com/IECSv1.11D4Help.zip
Delphi 5:
www.RiverSoftAVG.com/IECSv1.11D5Help.zip
Delphi 6:
www.RiverSoftAVG.com/IECSv1.11D6Help.zip
v2.01
Delphi 5:
www.RiverSoftAVG.com/IECSv2.0D5Help.zip
Delphi 6:
www.RiverSoftAVG.com/IECSv2.0D6Help.zip
|
Send mail to
webmasterNO@SPAMRiverSoftAVG.com with questions or comments about this web
site.
|