Friday, January 27, 2006

BDS2006 small features, great impact

It is always amazing how small things can have such a great impact on your daily work. The new features in the BDS2006 editor like live templates are obviouos because you can see it immediately while working in the editor. 'Small' improvements and features are discovered along the path.

Lately I noticed a tiny red bug (in dutch we call it a lieveheersbeestje) on a tab in the editor after debugging an application.

It seems that BDS2006 opens units, necessary for debugging, on the fly and implicit closes them when the debug session ends. (This is an editor option) If you stop debugging in such a unit Delphi keeps that unit open. Ain't that great?

I remember debugging a C# project in Visual Studio 2003 where I ended up with an endless list of tabs which is very annoying in my opinion. In VS you have the tabs for design and code besides each other on top of the editor. BDS2006 (and previous versions) have an extra tab at the bottom of the editor for switching between design and code. So in BDS2006 you always have the half amount of tabs in the top tab control compared with VS2003.

So these small features in BDS2006 are great! It gets even better if you popup the context menu on the tab. If you don't want BDS2006 to close the debugged units implicit(an editor option) you can close them by yourself using 'Close all pages opened while debugging' option. Hack you can even close all pages except the one that is active.

Small things, great stuff!

Tuesday, January 17, 2006

ECO Adventures: Inheritance

Inheritance is one of the five pilars of Object Oriented Programming. In ECO inheritance is, I can tell you now, a piece of cake.
Consider this 'real world' model:

Developer and SalesMan inherit the behavior from Person. Developer and SalesMan are specializations of Person. Implementing this model in a VCL Win32 application using TDataSet would consider a lot of work. For instance the, in fact one-on-one relation must be maintained in the database. A person is either a Developer or a SalesMan, a person can not be both. (if you don't agree you should read this blogpost :-) )
Anyway implementing this becomes, even in Delphi with TDataSet, more complex. In ECO it is a very straight forward process.

Create the windows (ECO) application
Drop three datagrids(dgPerson, dgDeveloper, dgSalesMan) on the form and three ExpressionHandles (ehPerson, ehDeveloper, ehSalesMan) And oh, don't forget to compile first!

Setting the ExpressionHandles
Roothandle->rhRoot (Don't forget to set the Roothandles EcoSpaceType property!)
Expression->Person.AllInstances (Use the OCL Editor here)



Setting the datagrids



To make things complete drop two buttons for the Developer and SalesMan grid. Connect the roothandle property to ehDeveloper and ehSalesMan and set the for both buttons the property ECOListAction to Add.

Well this is pretty much it! You can see that the grids have all the appropiate attributes for their classes. By running the application we can test it:

Notice that adding a developer or salesman automatic means adding a person. So again the model does all the hard work in the background.
While still scratching the surface of ECO it becomes clear that ECO is very powerfull framework, taking a lot of the work load. Making this little application with TDataSets would be harder (although it can be done). For instance after inserting the Developer you would have to code to get a person in the person table.

Guess what: We did not code at all!

Monday, January 16, 2006

Refactor all the way

After using BDS 2006 for three weeks now I must say it is a real piece of art. I can not think of one reason to go back to Delphi 7. For me the most valuable new features are the improved and extended refactorings. It takes some time to get used, using them, old habbits just don't disappear that easy :-) I guess.

What I always found a bit annoying in Delphi coding was the fact that changing the parameters of an existing method, meant a lot code cruising. OK, you can't have it all but figure this:

In Delphi 7, to change a parameter of a method you should do something similar like this:

1. Change the parameter in the implementation section (iow the method)
2. Surf (Ctrl-Click) to the interface section to change the decleration
3. Ctrl + Arrow Down to go back to the implementation

Delphi 2006, and in specific Together, dramatically improved things. With refactoring you can now change the parameterlist of a method, and Together will take care of changing the declaration (or vica versa)!

The 'Change Parameters' refactor dialog:

With this dialog you can add or alter parameters in a very easy way. Other 'My favourite' refactorings are:

  • Extract method (Existed already in D2005)
  • Find unit (Helps you finding the unit for the uses clause)
  • Declare variable

The new and improved refactorings in BDS 2006 boost productivity, no doubt about that. This and the other editor improvements, like Live templates, made upgrading to BDS2006 worthwhile.

Monday, January 09, 2006

Fooling around with TWebbrowser

For a project I needed to edit a HTML page within a Delphi Win32 application. Delphi has a TWebbrowser component which appeared to be suitable for this situation.
TWebbrowser in fact is a wrapper over Microsoft's Shell Doc Object and Control library (SHDOCVW.DLL) and it brings webbrowser functionality to your application. With a TWebbrowser it is easy to navigate the web and files. There are a lot resources to find on the internet, here I share some of my experiences.

Using TWebbrowser for editing
As said before I needed to edit a HTML webpage. You can get the Document (from the loaded webpage) with MSHTML, a library providing WYSIWYG editing for Internet Explorer and thus TWebbrowser. This HTMLDocument provides access to all the elements of a webpage, and allows you to edit the page visually.
After adding MSHTML to your uses clause you can get the document as follows:

Getting the document:
HTMLDocument2Ifc := (MyWebbrowser.Document as IHTMLDocument2);

Note that the webpage must be completed loaded otherwise the object will be nil.

With a IHTMLDocument2 interface object we can edit the webpage. Now for this project I needed to place links absolute on the page aligned with some body background. But the first thing we need to do is setting the document in edit mode.

Setting the document in edit mode:
HTMLDocument2Ifc.DesignMode := 'On'; //Use 'Off' to switch desingmode off

Setting the body background:
(HTMLDocument2Ifc.body as IHTMLBodyElement).background := AFileName; :='no-repeat';

Setting the document for absolute positioning (2-D positioning):
HTMLDocument2Ifc.execCommand('2D-Position', false,true);

Now we can drag the links (wrapped by a span) around on the webpage.

With the execCommand method you can easily do a lot of editing on selected text in the document. To name a few:

HTMLDocument2Ifc.execCommand('Bold', false,0);
HTMLDocument2Ifc.execCommand('Italic', false,0);

HTMLDocument2Ifc.execCommand('FontSize', false, 4); //Set the font size of selected text
HTMLDocument2Ifc.execCommand('InsertImage', true,0); //Use default insert image dialog

There is a lot more, check microsoft MSHTML site for everything.

Another feature of the HTMLDocument2 is that you can get collections of images, links and styles of the webpage. For example you could get all the picture sources as follows:

for i := 0 to HTMLDocument2Ifc.images.length -1 do

Item := HTMLDocument2Ifc.images.item(i, null) as Ihtmlelement;
lbItems.AddItem(Item.getAttribute('src',0) + ' [A Picture]', nil);

Well there is a lot more to explore, but it is easier then you might think at forehand. Here are some links with more resources, to fool around with, on TWebbrowser:

Microsoft MSHTML site
Webbrowser to the max (
Brian Cryer TWebbrowser page
MSHTML Editier modus German site with examples.
WebSVN Code examples.

Tuesday, January 03, 2006

ECO Adventures: Master-Detail

I finally have the time to play with ECO and learn about what it is.
In this episode of 'The ECO adventures' I create a Master-Detail model.

In VCL it is very easy to create a master-detail relationship between two datasets (TDataSets) using the mastersource property. In ADO.NET you can make such relations within the .net dataset, but implementing them is a bit different compared with the TDataSet.
In ECO, it is again relative easy to implement.

Making the model
Take this model, where we have Customers and Projects. This two objects has a relation, where a customer has zero or more projects, and a project belongs, of course, to one customer.
In ECO we can model it like this:

Take an extra look at the /Project attribuut. This is a derived attribuut, in this case showing the projectnumber (an integer) and the description in one field.
This can be done by OCL. The expression for this one is:

self.Number.asString + '-' + self.description

You can easily create this with the OCL expression editor.

I have created this model in a ECO Package, so that it can be used in multiple client applications. (Winform and ASP.NET)

Making the Winform Application
Just add a ECO Winform Application to your projectgroup with the ECO package and make a project reference to the ECO dll. In this case it is the MasterDetail.dll.
After setting the reference, you must select the package in the ECO space of the Winform application, to let the application know that it can use the package.

After that you must first recompile for further designtime support.

Now we can create the GUI. The form has standard a few ECO components, with among others the rhRoot, wich connects the form to the ECO space. (The reference to the model)
Select the ECO space in the ECOSpaceType property of the rhRoot.

Connecting to the object instances of our classes (Customers and Projects) we use ExpressionHandles, which are connected to the model through the roothandle (rhRoot).

To get the project details, we have to use a CurrencyManagerHandle, which has the grid (in general a GUI control) with Customers as the BindingContext. Through this handle we connect to projects of a specific Customer. (This is like the CurrencyManager in ADO.NET)

So let's make this GUI:

Create a new expressionhandler and call this ehCustomers.
Set properties as below:
  • Roothandle -> rhRoot
  • Expression -> Customer.AllInstances (Use the OCL editor for this by invoking it with the ... button)

Set the property DataSource of the customer grid to ehCustomers. Notice that the grid shows the column name already!
ECO has some strong listactions build in to invoke operations directly on your objects. Set the property ECOListAction of the button right from the grid to 'Add'. And the Roothandle to ehCustomers.

Run the application.

OK this works. So far pretty easy, isn't it? Well now we want to see the projects of a specific customer in the other grid.
Here we need the CurrencyManagerHandle. Drop a CurrencyManagerhandle on the form and set the properties as follows:

  • Name -> cmCustomer
  • RootHandle -> ehCustomers
  • BindingContext -> CustomerDataGrid

The currencymanagerhandle will select a single instance of a customer (iow the selected customer in the grid).

To get the projects we need to drop another Expressionhandle, with the following properties set:

  • Name -> ehProjects
  • RootHandle -> cmCustomer (yes the CurrencyManagerHandler...)
  • Expression -> self.Projects (To select in the OCL editor through the Roles node)

Connect the projectgrid to ehProjects and assign the button for the Add list action.

Run the application.

Well this was pretty much it. Set the property Autoform on the grids to true and you already have a complete working application.

ECO is a new way of programming (to me it is) .The way to use it is a little different compared to the database-driven approach although the main concept is the same. Keeping the business rules (like the relation) in the model is a strong benefit for the ECO approach. This was 'my first ECO application', and it was not all that hard. One thing to remember is to Compile your application often, this is needed for the designtime support I guess, otherwise you will sometime s look for property values you need which will not be there.

This ECO adventure will be continued...

Use an image as your UIBarButtonItem

Using an image as your UIBarButtonItem in your navigationcontroller bar can only be achieved by using a common UIButton as the BarButtonItem...