Archive for the ‘Clarion 7’ Category

Update for 7.2

Wednesday, June 30th, 2010

We just released an update for 7.2 with a nice mix of fixes and changes to both the IDE and the RTL. If you are a template writer then note that we’ve bumped the template version number to 7.2/7200.

You can check the readme list here

Coming up with 7.2

Tuesday, June 1st, 2010

There was a recent thread in the news group where a lot of people were saying how much they used (and missed) the availability of a list of an Applications’ Procedures. Seems that code completion wasn’t the best option when you can’t remember the name of the Procedure. And its quite understandable when you have many many procedures, possibly hundreds, in your .App. So thanks to some quick work by Diego, Scott and Alexey, we were able to slip this this new feature into the 7.2 release; the Data pad now has a “Procedures” node, and when selected it lists all template based procedures, the Procedures node is only activated when you are in any of the editors, and dbl-clicking on a procedure name in the list inserts the procedure name into the editor. The Procedures list also has a Windows Explorer style incremental locator.

proclist

Update for 7.1

Friday, April 30th, 2010

An update for 7.1 is going out today, there are no new features introduced in this release, but there is a change (for the better) that you’ll soon have:

CHANGE: Code generation only executes from the application tree window, this prevents generation with partial or unsaved changes and ensures consistency for code generation.

What this new change boils down to is a subtle (or not so subtle, depending on your work style) change to where and when you can initiate code generation. In all previous releases the IDE was very loose about allowing you to initiate code generation from just about anywhere within the Application Generator dialogs and supporting components (Designers, Embed Editor, etc.), without consideration for the current state of uncommitted changes, and unfortunately this flexibility opened up avenues for introducing problems into the generated code. Imagine if you changed a Window or Report and exited the Designer, now the structure has changed but you haven’t committed the changes at the Procedure level, but while still on Procedure Properties you execute code generation. What should generate? Should AppGen somehow restore the old structure (probably not what you want), or auto-commit the changes to the Procedure, again not a decision that should happen without an explicit choice by the developer. The implemented solution for this is very simple, the AppGen will inform you to return to the main window, which in turn forces you to either save the partial changes or abort them. The result is 100% consistency in the generated code, at the cost of having to make an explicit decision to save or abort changes at the Procedure level. Besides this change (for the better and safer) there are a good number of other fixes. You can read the entire list here

XML with Clarion 7 - Part 2

Thursday, March 25th, 2010

For this article we’ll dive further into the processing of XML files. There are two types of XML we may encounter, #1 well formed XML, #2 unknown XML files.

#1 (well formed XML) documents are XML files that are correct in their syntax and will not require any validation, for this type of file we know from where they come from, and we know their format.
#2 (unknown XML) are documents that we don’t know where they come from, or if they are syntactically correct and well formed.
For the second type we won’t worry about because in this article we will be talking about how to read well formed files, the type of files that are created by  an automated process  to communicate between programs and share information, all that is done using well formed, well known XML documents.

When we want to communicate with another program through an XML document we need to be able to write that document and to read that document.
In this type of exchange the XML format used in that document is a well known format.
We already saw how to write our XML document using the XMLGenerator class which creates a well formed document, and now we need to Read a “received” document.

The Reading.

For reading an XML document a new class was recently added in C7; that class is the XMLParser. The XMLParser is a class that reads an XML document file and processes it, the document must be a valid document because the XMLParser does not validate the document, that is why we call the XMLParser a non-validating XML parser.

Is a no-validating parser bad?
Well no, it is not bad, it is just that, a non-validating parser.
Because we will be reading a known file we don’t need to validate the files and we don’t need to loose any time in doing that.
We are not creating a program that can read any random XML file, we only need to read a specific XML document.
For that kind of file we don’t need any validation, we know the format and it is what we are expecting.

The XMLParser included in C7 is very fast and its memory usage is very low. The parser does not store or create any structure with the XML data, instead it uses an interface and calls each method of that interface passing the XML Data.
To use the parser the IXmlNotify interface needs to be implemented.

The IXmlNotify is an interface declared in the file QuickXMLParser.INC, the same file where the XMLParser is declared.

The question is then:

Why I need to implement the IXmlNotify to parse my XML file?
The XMLParser does all the work of parsing the file but it does not know what to do with the data that comes from the XML Document.
We need to “tell” the parser what to do with the data. Or in this case the parser will just inform us that it found some data and let us decide what to do with it.
So the parser just reads the data and passes it to us.

How is the data is passed to us?
The parser calls the correct methods from the IXmlNotify interface based on the data that it reads.

A quick look into the IXmlNotify interface will show that the methods are very simple.

IXmlNotify      INTERFACE
FoundNode           PROCEDURE( STRING name, STRING  attributes )
FoundElement        PROCEDURE( STRING name, STRING  value, STRING  attributes )
CloseElement        PROCEDURE( STRING name)
StartElement        PROCEDURE( STRING name, STRING  value, STRING  attributes )
EndElement          PROCEDURE( STRING name, STRING  value, STRING  attributes )
FoundComment        PROCEDURE( STRING Comment)
FoundHeader         PROCEDURE( STRING attributes)
CloseHeader         PROCEDURE()
FoundAttribute      PROCEDURE( STRING tagname, STRING name, STRING  value )
                END

Not that many methods to implement, right?

It is easy to implement the IXmlNotify, just declare a class like this:

MyClass CLASS,IMPLEMENTS(IXmlNotify)
END

And implement the IXmlNotify methods like:

MyClass.IXmlNotify.FoundNode           PROCEDURE( STRING name, STRING  attributes )
CODE

In each of the methods you implement you just write the code that is needed every time the parser finds some data that you are interested in.
Remember that this is not a general purpose parser so you will know exactly the data that you will be receiving.

After you have you class implemented just call the parser like:

lXMLParser XMLParser
LOC:XMLStream  STRING(1024)
CODE
lXMLParser.Parse(LOC:XMLStream,MyClass.IXmlNotify)

Note: you can declare your string on run time based on the size of the XML file or you can receive the stream from a web server,etc.

Most of the time you will have to parse a FILE, and that is why we extended the parser class to support a FILE name.

You still need to tell the Parser what to do with the data that it is parsing, but now instead of implementing the IXmlNotify interface you just derive the VIRTUAL methods needed.
And after that you just call your class like this:

XML.Parse(fileName)

Only one method call and the XML Document was parsed and the data was processed as you indicated.
With the Virtual methods you only derive the methods that are called with the data you are interested in, so you don’t need to derive all the methods.

The following are the all the methods that are virtuals

XmlNotifyFoundNode           PROCEDURE(STRING name, STRING  attributes),VIRTUAL
XmlNotifyCloseNode           PROCEDURE(STRING name),VIRTUAL
XmlNotifyFoundElement        PROCEDURE(STRING name, STRING  value, STRING  attributes),VIRTUAL
XmlNotifyCloseElement        PROCEDURE(STRING name),VIRTUAL
XmlNotifyStartElement        PROCEDURE(STRING name, STRING  value, STRING  attributes),VIRTUAL
XmlNotifyEndElement          PROCEDURE(STRING name, STRING  value, STRING  attributes),VIRTUAL
XmlNotifyFoundComment        PROCEDURE(STRING Comment),VIRTUAL
XmlNotifyFoundHeader         PROCEDURE(STRING attributes),VIRTUAL
XmlNotifyCloseHeader         PROCEDURE(),VIRTUAL
XmlNotifyFoundAttribute      PROCEDURE(STRING tagname, STRING name, STRING  value),VIRTUAL

As you can see each one match a method in the IXmlNotify.

Summarizing both articles, an XML file is just a formatted text file, we can read the data contained by hand using a simple ASCII FILE but then we need to parse the file to extract the content, to make that process much easier we use the XMLFileParser class. To create a new XML file instead of just writing out the text we use the XMLGenerator class to simplify the process of creating the Tags and maintain the open/close of notation tags, also it ensures that we create a well formed XML document, and gives us the flexibility to create any type of XML document that we need in our program.

Attached is an example on how to create a class that derives the methods to load a tree with the parsed document.

part2_xmlparser

Template Tips #3 - #ATEND vs #AT(%AfterGeneratedApplication)

Tuesday, March 23rd, 2010

It looks like the embed %AfterGeneratedApplication is a very popular embed these days.
We already talked about it in the Template Tips #2 post where we compare it with the #AT(%ProgramEnd). Now we’ll compare #AT(%AfterGeneratedApplication) with #ATEND, and we’ll explain which of these is appropriate for a given task.

Why do we compare #ATEND with #AT(%AfterGeneratedApplication) ?
Because both of these are executed at the end of the code generation process (when we click on the Generate button).
Some 3rd Party Templates have the need to execute code that requires the App to be have been generated, and you’ll find they make use of #ATEND or #AT(%AfterGeneratedApplication).

All of the templates support #ATEND, but we’ll focus on the #APPLICATION #ATEND embed.
The #ATEND is comparable to a Destructor of a class, it is executed at the end of a templates code generation cycle, and the purpose is typically to execute some clean up code. When I mention clean up code I’m not talking about generating backups, creating extra files, or doing some extra  processing, etc. I’m talking about cleaning up template symbol values. Any other processing should not be executed in the #ATEND.

One of the reasons additional processing should not be executed in the #ATEND is that the #ATEND is similar to a Class Destructor, and that means the scope of the template is already ending, so just like in any other Class Destructor. you should not be creating new instances of anything at that point.

Another reason, that is more related to the templates is the Embeditor. What does the Embeditor have to do with the #APPLICATION #ATEND?
Well if you inspect the #APPLICATION code closely you will see that there is one magic part that make the Embeditor work.

I’m talking about this code:

#IF (%EditProcedure)            #! Special for editing embedded source in context
  #CREATE(%EditFilename)
  #FIND(%ModuleProcedure,%EditProcedure)
  #FIX(%Procedure,%ModuleProcedure)           #! Fix current procedure
  #MESSAGE('Generating Module:    ' & %Module,1) #! Post generation message
  #MESSAGE('Generating Procedure: ' & %Procedure,2) #! Post generation message
  #GENERATE(%Procedure)                       #! Generate procedure code
  #COMMENT(60)                                #!Set comment alignment to column 60
  #CLOSE
  #ABORT                                      #!Stop execution of any other code
#ENDIF

Yes, the Embeditor code is just the #GENERATION of the procedure with a little bit of magic.

Because this code is executed in the #APPLICATION section of the template we are expecting the #APPLICATION #ATEND to be executed.
Actually everything would be executed if it was not for the #ABORT at the end of the above code.
So if you are using the #ATEND, you are not only adding code to the equivalence of a Class Destructor, but you are also adding code that will always be executed unless you check for the value of the %EditFilename symbol. If the value of %EditFilename is null then you can be sure that you are in regular code generation, and not in the Embeditor generation. This is a very important point.

Where does the #AT(%AfterGeneratedApplication) fit into all this code generation?
Well the #EMBED(%AfterGeneratedApplication) is located at the end of the #APPLICATION template, it’s the last code to be generated before the #ATEND, but the big difference is that it only executes when we are generating the #APPLICATION during regular code generation. The execution of that embed will not happen on the Embeditor generation because of the #ABORT that we already mentioned.

The conclusion, if you need to execute code at the end of the Application generation process, I always recommend the use of the #AT(%AfterGeneratedApplication) instead of the #ATEND. And always try to use a PRIORITY, that will make other templates play nice with yours.