Friday, October 15, 2010

Delphi Tip : Avoiding Project101

It is inevitable. In my hurry to test something I created yet another console application and started entering some code. Funny thing how the project numbers keep mounting, and I have no recollection what any of these small test applications do since every default project goes into the same directory.

The solution turned out to be quite simple. Remove the WRITE access to the default project directory for my development user account. Now when I go to save, I am presented by the following dialog:



This gives me one last warning that the project doesn't yet have a home...I can now decide where to place it and what it will be called. Actually, I can't even RUN the application until it has a home...

Granted this means that there will probably be another directory with a hundred ProjectN programs... but I'll know I put them there on purpose.

Friday, December 19, 2008

Delphi Wizard Framework - SetAllowDeletion

In my previous posts about my wizard framework, I discussed some of the original design decisions, as well as how to perform simple forward navigation.

The Delphi Wizard Framework is currently being hosted by google code hosting, which I briefly reviewed in a previous post.

One of the problems that I ran into quickly after starting this system was the issue of displaying a wizard form that doesn't allow user input but is there to show the user that something is being performed, to please wait patiently. The wizard framework as it navigates from one form to another automatically adds the last form displayed to the deleted queue and sends itself a message which will free all the forms in the queue. This works great and performing cleanup, but can cause access violations if someone wants to do something like the following:

begin
fWizMgr.NavigateToPage('TStatuspage');
if not Supports(fWizMgr.CurrForm,IWizPerformStatus,StatusForm) then
raise Exception.Create('form does not support IWizPerformStatus');
for ix := 0 to 100 do
begin
StatusForm.DoWork(ix);
StatusForm.ShowProgress(ix);
Application.ProcessMessages;
end;
fWizMgr.NavigateToPage('TResultspage',false);
end;

Now the intentions here are good, but the second the ProcessMessages is handled by the system the form which is executing this code is going to be freed, which will ultimately generate an exception. The solution to this is to use the framework method SetAllowDeletion to delay the deletion of the current form until later. Using it the correct method of the above routine should look like the following:

begin
fWizMgr.SetAllowDeletion(false);
try
fWizMgr.NavigateToPage('TStatuspage');
if not Supports(fWizMgr.CurrForm,IWizPerformStatus,StatusForm) then
raise Exception.Create('form does not support IWizPerformStatus');
for ix := 0 to 100 do
begin
StatusForm.DoWork(ix);
StatusForm.ShowProgress(ix);
Application.ProcessMessages;
end;
fWizMgr.NavigateToPage('TResultspage',false);
finally
fWizMgr.SetAllowDeletion(True);
end;
end;

Sunday, December 14, 2008

The Delphi Wizard Framework - Navigation

In a previous entry, I discussed some of the design decisions that allowed me to reach the current solution. One more decision which greatly impacted the design of the framework... I wanted to make sure that it could be data driven.

One of the projects that I was working on at the time was an editor for an XML datafile. For simplicity sake, the file had a structure something like the following:

<data>
<book>
<author>
<name>Steven King</name>
</author>
</book>
<movie>
<director>
<name>Stanley Kubrick</name>
</director>
</movie>
</data>

The goal of the program was to create an editor that could handle each child element. I created two forms, one named tBookWizardForm and another named tMovieWizardForm. Invoking these pages from the first page of the wizard looked something like the following:

procedure EditChild(ChildNode:IXmlNode);
var
NodeAware : IXmlNodeAware;
begin
fWizMgr.NavigateToPage('T'+ChildNode.NodeName+'WizardForm');
if Supports(fWizMgr.CurForm,IXmlNodeAware,NodeAware) then
NodeAware.SetXmlNode(ChildNode);
end;

Note in this example: The call to NavigateToPage automatically inserts the current page into the "to be deleted" list so there is no need to perform any manual cleanup.

The interface IXmlNodeAware actually exists in another unit which is shared by both wizard forms, it looks like the following:

type
IXmlNodeAware = interface
['{F78DF157-CBAF-48A3-BC4C-CE338514C898}']
Procedure SetXmlNode(Node:IXmlNode);
end

This would automatically perform the dispatch to the proper wizard form, if it ran into a node which it did not understand, it would generate an exception which would be handled and displayed by the wizard manager (displays a dialog that states that the requested form was not registered).

In my next post, I will cover SetAllowDeletion, and why one would need to use it.

Wednesday, December 10, 2008

Google Code Hosting -- Painless Open Source Management

Google Code Hosting really makes it simple to host open sourced projects. Especially if you like Subversion. In my few days with it I have tried just about all of the basic features and have found them easy to use and manage. Initial setup was very painless. The only desirable thing that is missing would be some method of adding to an rss/atom feed. Wait, thats what my blog and twitter are for.