OOP and XML usage

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

OOP and XML usage

Graeme Geldenhuys-2
Hi,

The small project I am working on requires reading a XML file and using
that data for various things, including building a GUI interface.

Most of my projects are database driven and uses the tiOPF framework to do
my load/saving work (plus a lot of other things).

As the title says, all my applications are normally object driven. This new
project I am working on should not be any different. One big difference
though is that it is not database driven and I don't want to bind it to
tiOPF framework.

So at the moment I reading the xml file and building my own object model
based on the various elements and attributes in the XML file.

Example:

-----
<?xml version="1.0" standalone="yes"?>
<install desc="my description" version="0.9">
  text for install element
  <eula>xxxx</eula>
  <eula lang="af">xxxxx</eula>
</install>
----

...would translate to classes as follows: elements become classes and
attributes become properties...

 TSetupFile
 TInstall
 TEULAList
   TEULA

Interfaces section of TInstall might look like this....

  TInstall = class(TObject)
  public
    property Text: string...      // 'text for install element'
    property Desc: string...      // 'my description'
    property Version: string      // '0.9'
    property EulaList: TEULAList .....
  end;


This makes sense to me, and this is the design I am used to following with
tiOPF based projects. But like I said, I am not using tiOPF this time and I
am working with a XML file, which I haven't worked with before.


Am I taking the right OOP approach here, or should I rather be working with
the dom unit and TXMLDocument, TXMLElement etc classes directly. At the
moment I do not require writing to the XML file, only reading. At a much
later date, I'll be writing to the XML file though.

I feel my approach of using my own specialized classes is a better fit
compared to the generic TXMLElement classes. But I just want to confirm my
thoughts and also ask...

   How do other developers use XML files?


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Michael Van Canneyt


On Wed, 27 Jan 2010, Graeme Geldenhuys wrote:

> Hi,
>
> The small project I am working on requires reading a XML file and using
> that data for various things, including building a GUI interface.
>
> Most of my projects are database driven and uses the tiOPF framework to do
> my load/saving work (plus a lot of other things).
>
> As the title says, all my applications are normally object driven. This new
> project I am working on should not be any different. One big difference
> though is that it is not database driven and I don't want to bind it to
> tiOPF framework.
>
> So at the moment I reading the xml file and building my own object model
> based on the various elements and attributes in the XML file.
>
> Example:
>
> -----
> <?xml version="1.0" standalone="yes"?>
> <install desc="my description" version="0.9">
>  text for install element
>  <eula>xxxx</eula>
>  <eula lang="af">xxxxx</eula>
> </install>
> ----
>
> ...would translate to classes as follows: elements become classes and
> attributes become properties...
>
> TSetupFile
> TInstall
> TEULAList
>   TEULA
>
> Interfaces section of TInstall might look like this....
>
>  TInstall = class(TObject)
>  public
>    property Text: string...      // 'text for install element'
>    property Desc: string...      // 'my description'
>    property Version: string      // '0.9'
>    property EulaList: TEULAList .....
>  end;
>
>
> This makes sense to me, and this is the design I am used to following with
> tiOPF based projects. But like I said, I am not using tiOPF this time and I
> am working with a XML file, which I haven't worked with before.
>
>
> Am I taking the right OOP approach here, or should I rather be working with
> the dom unit and TXMLDocument, TXMLElement etc classes directly. At the
> moment I do not require writing to the XML file, only reading. At a much
> later date, I'll be writing to the XML file though.
>
> I feel my approach of using my own specialized classes is a better fit
> compared to the generic TXMLElement classes. But I just want to confirm my
> thoughts and also ask...
>
>   How do other developers use XML files?

Yes.
I use DOM to read the file, and then translate the found TDOMElement nodes to
the actual business classes.

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Graeme Geldenhuys-2
Michael Van Canneyt wrote:
>
> Yes.
> I use DOM to read the file, and then translate the found TDOMElement nodes to
> the actual business classes.

Thanks for the quick response. I'm glad I am on the right track and my idea
is not totally dumb founded. :)


Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Leonardo M. Ramé
In reply to this post by Graeme Geldenhuys-2
I use a similar approach in a systems integration product for a hospital, it communicates different systems by XML files. The app receives an XML with data related to an radiology study, then parses the file and convert it to an object, do some checkings and transformations, and store the object to a database or reject the message.

Most tags are parsed automatically because them have a one-to-one relation to the object's properties, and with others we had to create custom associations.

How it works:
1) Create an instance of FCL-XML's TXMLFile class, let's call it lXMLDoc, and use ReadXMLFile to parse the file.

2) Create a method called, for example ProcessChildNode, as follows:

procedure TMyClass.ProcessChildNode(ANode: TDomNode);
begin
  while Assigned(ANode) do
  begin
    case ANode.NodeType of
      ELEMENT_NODE: begin
        if ANode.ParentNode.ParentNode <> nil then
          NodeEvent(ANode);
      end;
      ATTRIBUTE_NODE:;
      TEXT_NODE, CDATA_SECTION_NODE: begin
        if ANode.ParentNode.ParentNode <> nil then
           NodeEvent(ANode);
      end;
    end;

    if ANode.HasChildNodes then
      ProcessChildNode(ANode.FirstChild);
    ANode := ANode.NextSibling;
  end;
end;

3) Create the NodeEvent method:

procedure TMyClass.NodeEvent(ANode: TDomNode);
begin
  case ANode.NodeType of
    TEXT_NODE,
    CDATA_SECTION_NODE:
       { using RTTI set properties of FMyObject }
       SetPropValue(FMyObject, ANode.NodeName, ANode.NodeValue);
    // ...
    // more types
  end;
end;

4) After loading the XML file, let's call ProcessChildNode(lXMLDoc.FirstChild) this is a recursive method which will traverse all the XML tree, and it will call the NodeEvent method on only certain types of nodes (look at ProcessChildNode method). In NodeEvent, the value of the node is set to the PUBLISHED!!!! object's properties by using RTTI, of course, if your XML file doesn't match one-to-one with your object, you can avoid using RTTI and do the assignments by hand.

A side note, if your target object, apart from having plain types, it includes properties of type Object, you can adapt the NodeEvent method, and check for ANode.ParentNode.NodeName = 'MyInnerObject', then set FMyObject.MyInnerObject.SomeProperty. That's the way we use to populate an object from an XML file.

Leonardo M. Ramé
http://leonardorame.blogspot.com


--- On Wed, 1/27/10, Graeme Geldenhuys <[hidden email]> wrote:

> From: Graeme Geldenhuys <[hidden email]>
> Subject: [fpc-pascal] OOP and XML usage
> To: "FPC-Pascal users discussions" <[hidden email]>
> Date: Wednesday, January 27, 2010, 6:47 AM
> Hi,
>
> The small project I am working on requires reading a XML
> file and using
> that data for various things, including building a GUI
> interface.
>
> Most of my projects are database driven and uses the tiOPF
> framework to do
> my load/saving work (plus a lot of other things).
>
> As the title says, all my applications are normally object
> driven. This new
> project I am working on should not be any different. One
> big difference
> though is that it is not database driven and I don't want
> to bind it to
> tiOPF framework.
>
> So at the moment I reading the xml file and building my own
> object model
> based on the various elements and attributes in the XML
> file.
>
> Example:
>
> -----
> <?xml version="1.0" standalone="yes"?>
> <install desc="my description" version="0.9">
>   text for install element
>   <eula>xxxx</eula>
>   <eula lang="af">xxxxx</eula>
> </install>
> ----
>
> ...would translate to classes as follows: elements become
> classes and
> attributes become properties...
>
>  TSetupFile
>  TInstall
>  TEULAList
>    TEULA
>
> Interfaces section of TInstall might look like this....
>
>   TInstall = class(TObject)
>   public
>     property Text: string...     
> // 'text for install element'
>     property Desc: string...     
> // 'my description'
>     property Version: string     
> // '0.9'
>     property EulaList: TEULAList .....
>   end;
>
>
> This makes sense to me, and this is the design I am used to
> following with
> tiOPF based projects. But like I said, I am not using tiOPF
> this time and I
> am working with a XML file, which I haven't worked with
> before.
>
>
> Am I taking the right OOP approach here, or should I rather
> be working with
> the dom unit and TXMLDocument, TXMLElement etc classes
> directly. At the
> moment I do not require writing to the XML file, only
> reading. At a much
> later date, I'll be writing to the XML file though.
>
> I feel my approach of using my own specialized classes is a
> better fit
> compared to the generic TXMLElement classes. But I just
> want to confirm my
> thoughts and also ask...
>
>    How do other developers use XML files?
>
>
> Regards,
>   - Graeme -
>
> --
> fpGUI Toolkit - a cross-platform GUI toolkit using Free
> Pascal
> http://opensoft.homeip.net/fpgui/
>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>



_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
i dont like this way of working with XML files...

im creating my own model using an Class factory and RTTI properties.

you register your classes in the class factory and the XML loader uses
a class function to select wich one to create for a given node. This
lets you have a lot more control over the process.

the same objects can save theyselves into another XML file thru a
property called AsXML.


Class Function XMLTag: String; Virtual;
and
Function AsXML : String; Virtual;

im using this to develop a Component system for Powtils... (But can be
used wherever needed)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Anthony Walter-3
I've written some XML classes which expose themselves as interfaces.
Usage goes something like this:

procedure SaveSettings(const Settings: string);
var
  Document: IDocument;
  Filer: IFiler;
begin
  Document := CreateDocument;
  Filer := Document.ForceRoot('test') as IFiler;
  Filer.WriteTime('time', Now);
  Filer.WriteString('application', Application.ExeName);
  Document.SaveToFile(Settings);
end;

<test><time>21:11:17</time><application>test.exe</application></test>

procedure ShowPerson;
var
  Document: IDocument;
  Root: INode;
begin
  Document := CreateDocument;
  Filer := Document.ForceRoot('data');
  Root.ForceNode('person/age').Value = 17;
  Root.FindNode('person[age = 17]').Filer.Write('Jason');
  Root.Filer.Write('person/salary', 10000);
  ShowMessage(Document.Text);
end;


<data><person><age>17</age><name>Jason</name><salary>10000</salary></person><data>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
with my system would be simply something like

Type
   TMyClass = Class(TXMLNode)
   Private
     fSomething : String;
   Public
     Constructor Create(Const aInstanceName : String); Override;
     Class Function XMLTag: String; Override;
   Published
     Property Something : String Read fSomething Write fSomething;
   End;

Constructor Create(Const aInstaceName  : String);
Begin
  Inherited Create(aInstanceName);
End;

Class Function XMLTag: String;
Begin
  Result := 'MyTag';
End;

Factory.Register(TMyClass);


Whenever the xml loader finds a <mytag something="test"/> it will
create an instance of TMyClass and set the published properties
accordingly (Using RTTI)...

Theres another procedure (wich is virtual and can be overriden if
needed) that triggers events across the three... (wich are basically
dotted notation names...)

MyClass1.MyClass2.Test <-

Finds instance MyClass1,
Finds instance MyClass2 that is a child of MyClass1

then issues a DispatchStr in MyClass1 with Test as the message
string... (The pointer can be passed as to hold properties, values,
etc)...

(Im using this message system to allow brower events to be sent to
server side objects)

2010/1/27 Anthony Walter <[hidden email]>:

> I've written some XML classes which expose themselves as interfaces.
> Usage goes something like this:
>
> procedure SaveSettings(const Settings: string);
> var
>  Document: IDocument;
>  Filer: IFiler;
> begin
>  Document := CreateDocument;
>  Filer := Document.ForceRoot('test') as IFiler;
>  Filer.WriteTime('time', Now);
>  Filer.WriteString('application', Application.ExeName);
>  Document.SaveToFile(Settings);
> end;
>
> <test><time>21:11:17</time><application>test.exe</application></test>
>
> procedure ShowPerson;
> var
>  Document: IDocument;
>  Root: INode;
> begin
>  Document := CreateDocument;
>  Filer := Document.ForceRoot('data');
>  Root.ForceNode('person/age').Value = 17;
>  Root.FindNode('person[age = 17]').Filer.Write('Jason');
>  Root.Filer.Write('person/salary', 10000);
>  ShowMessage(Document.Text);
> end;
>
>
> <data><person><age>17</age><name>Jason</name><salary>10000</salary></person><data>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
im actually needing better RTTI as to allow easier method invocation...

But generally i feel my way of doing XML is better than FPC defaults
(Too generic, tries to solve too many problems with the same code)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Michael Van Canneyt


On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote:

> im actually needing better RTTI as to allow easier method invocation...
>
> But generally i feel my way of doing XML is better than FPC defaults
> (Too generic, tries to solve too many problems with the same code)

What exactly do you mean by FPC defaults ?

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Graeme Geldenhuys-2
In reply to this post by Jorge Aldo G. de F. Junior
On 28 January 2010 16:10, Jorge Aldo G. de F. Junior <[hidden email]> wrote:
>
> Whenever the xml loader finds a <mytag something="test"/> it will
> create an instance of TMyClass and set the published properties
> accordingly (Using RTTI)...

I like that idea, but how flexible is? By that I mean, I have nested
tags (using the same element name) that I need to load. Something like
a dependency tree. My custom object model can handle this without
problems, but I'm still curious about your solution.

Example XML, and there isn't a limit to the nesting of options.

<install>
  <option>Option 1</option>
  <option>Base database support
    <option>Firebird drivers
      <option>Windows</option>
      <option>Linux</option>
    </option>
    <option>MySQL drivers</option>
  </option>
</install>


--
Regards,
  - Graeme -


_______________________________________________
fpGUI - a cross-platform Free Pascal GUI toolkit
http://opensoft.homeip.net/fpgui/
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
each tag generates a new instance of the class

you can add a property (that all objects have) called InstanceName

<option instancename="blabla">something</option>

using the instance name the class factory can differentiate from other
instances (factory.instance['blabla'] retrieves the correct instance,
or, factory.dotnotation['roottag.nexttag.blabla'] retrieves by dotted
notation..

or

if you dont specify an instance name the factory will generate one randonly...

and actually i prefer to setup properties of objects using xml
properties instead of xml text

<tcpserver ip="192.168.1.1" port="80"/> instead of
<tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver>

2010/1/28 Graeme Geldenhuys <[hidden email]>:

> On 28 January 2010 16:10, Jorge Aldo G. de F. Junior <[hidden email]> wrote:
>>
>> Whenever the xml loader finds a <mytag something="test"/> it will
>> create an instance of TMyClass and set the published properties
>> accordingly (Using RTTI)...
>
> I like that idea, but how flexible is? By that I mean, I have nested
> tags (using the same element name) that I need to load. Something like
> a dependency tree. My custom object model can handle this without
> problems, but I'm still curious about your solution.
>
> Example XML, and there isn't a limit to the nesting of options.
>
> <install>
>  <option>Option 1</option>
>  <option>Base database support
>    <option>Firebird drivers
>      <option>Windows</option>
>      <option>Linux</option>
>    </option>
>    <option>MySQL drivers</option>
>  </option>
> </install>
>
>
> --
> Regards,
>  - Graeme -
>
>
> _______________________________________________
> fpGUI - a cross-platform Free Pascal GUI toolkit
> http://opensoft.homeip.net/fpgui/
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
In reply to this post by Michael Van Canneyt
i mean that FPC-XML tries to be too general and this leads to too
cumbersome code in various situations (FPC-XML is clearly overkill for
my needs).

2010/1/28 Michael Van Canneyt <[hidden email]>:

>
>
> On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote:
>
>> im actually needing better RTTI as to allow easier method invocation...
>>
>> But generally i feel my way of doing XML is better than FPC defaults
>> (Too generic, tries to solve too many problems with the same code)
>
> What exactly do you mean by FPC defaults ?
>
> Michael.
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
but theres a flaw in my model (that doesnot means much in what im doing):

the properties in the XML file must match exactly the properties each
object has.

else the properties are lost..

(the xml file can have less properties than the object but not the
other way around: the xml loader cannot force an object to have a
published -rtti- property that it doesnt have in code).
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
"Example XML, and there isn't a limit to the nesting of options."

no theres no limit for nested tags, they are stored in a tree plus a
linear list indexed by instance names

(nodes without instance names will receive a random instance name -
and be basically out of reach by the linear list - but will be still
reachable by walking the tree)

sorry for so much emails, im in a hurry.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Michael Van Canneyt
In reply to this post by Jorge Aldo G. de F. Junior

On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote:

> i mean that FPC-XML tries to be too general and this leads to too
> cumbersome code in various situations (FPC-XML is clearly overkill for
> my needs).
>


But FPC-XML is not meant for storing objects. It is meant to
read any correctly formed XML file that you may find.

FPC-XML is not something we invented. It is an implementation of
an official W3 specification. (www.w3.org)

Having this specification available means that we can read/write
any XML document out there that conforms to this spec, in a standard
manner. Since the programmer does not always control the XML he/she
gets, sticking to the specifications means we're sure we'll we able
to handle any XML thrown at us.

That is why we implement FCL-XML. Sooner or later the day comes
when you'll need it's features, trust me :-)

Michael.

> 2010/1/28 Michael Van Canneyt <[hidden email]>:
>>
>>
>> On Thu, 28 Jan 2010, Jorge Aldo G. de F. Junior wrote:
>>
>>> im actually needing better RTTI as to allow easier method invocation...
>>>
>>> But generally i feel my way of doing XML is better than FPC defaults
>>> (Too generic, tries to solve too many problems with the same code)
>>
>> What exactly do you mean by FPC defaults ?
>>
>> Michael.
>> _______________________________________________
>> fpc-pascal maillist  -  [hidden email]
>> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Graeme Geldenhuys-2
In reply to this post by Jorge Aldo G. de F. Junior
Jorge Aldo G. de F. Junior wrote:
> and actually i prefer to setup properties of objects using xml
> properties instead of xml text
>
> <tcpserver ip="192.168.1.1" port="80"/> instead of
> <tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver>

Both examples are valid XML, so I don't see any issue the way I am using
it. My previous example was just that, an example. My actual XML uses both
tag attributes and element text. The later is mainly used for longer text
in my xml file.



Regards,
  - Graeme -

--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://opensoft.homeip.net/fpgui/

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: OOP and XML usage

Jorge Aldo G. de F. Junior
using my system you can retrieve the text by a typecast

mytag.first;
mytag.findofclass(TXMLText); <- will stop the search at the first
object of specified class
If mytag.child is TXMLText Then <- to guarantee that we have found something
  WriteLn((mytag.child as TXMLText).Content); <- will print the
contents of the text

or if you know the text position between the child tags

writeln((mytag.childs[0] As TXMLText).Content);

but this is a way quite harder than a simple

WriteLn(mytag.properties['ip']); <- will return the property or '' if
not set (the object constructor can setup defaults)

thats why i prefer tag properties instead of xml text...

later you can save the objects with

Var F : Text;
Begin
  Assign(F, 'myfile.xml');
  Rewrite(F);
  WriteLn(F, MyTag.AsXML);
  Close(F);
End;

2010/1/29 Graeme Geldenhuys <[hidden email]>:

> Jorge Aldo G. de F. Junior wrote:
>> and actually i prefer to setup properties of objects using xml
>> properties instead of xml text
>>
>> <tcpserver ip="192.168.1.1" port="80"/> instead of
>> <tcpserver><ip>192.168.1.1</ip><port>80</port></tcpserver>
>
> Both examples are valid XML, so I don't see any issue the way I am using
> it. My previous example was just that, an example. My actual XML uses both
> tag attributes and element text. The later is mainly used for longer text
> in my xml file.
>
>
>
> Regards,
>  - Graeme -
>
> --
> fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
> http://opensoft.homeip.net/fpgui/
>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal
>
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal