QTX RTL, experimental Smart Pascal run-time library
The Smart MobileStudio RTL I designed primarily for mobile applications, and it does a damn fine job at managing that – but what about larger and different form-factors? What about applications designed for a full desktop browser? Or even better, compatibility with native Delphi?
Well this is essentially what the QTX RTL is all about: To have a platform for RTL experimentation and evolution, a kitchen-sink where we try stuff out before it’s released into the wild and merged with Smart Mobile Studio’s RTL.
Since I have just begun architecting this one there is still a lot of work ahead, but here is the general class hierarchy:
- Built-in error management at the core
- Built-in persistent mechanism (RTTI is optional)
- No dependencies on low-level procedures
- Delegate support
- Interface driven
This is a topic that must be explained a bit more in-depth, as it is extremely important and beneficial. Delphi and other Object Pascal compilers dont use delegate objects, they use what can only be called “ad-hoc” event handlers. In essence, Delphi events are nothing more than a bare-bone callback mechanism. This is extremely fast and effective, but limited to only one receiver at any given moment.
A delegate however, is an object wrapper around a classical event handler. You could say that it represents an object-oriented version of the ad-hoc mechanism. And it comes with the benefit you would expect from OOP, namely that you can create as many object instances as you wish. In other words, you can have 10 delegates responding to the same event if you so choose (!).
This is extremely efficient for component writers, because descendants can now respond to the same events as their ancestor methods without interfering or having to override anything. You also get away from the classical Delphi-style exposure of event trigger procedures (like below), which is quite frankly unnecessary bloat.
Procedure TMyComponent.DoChanged; Begin if not (csDestroying in ComponentState) and assigned(OnChanged) then onChanged(self); end;
Another nice feature of Delegate objects, is that they are resource efficient. If you only listen for one event, then no resources or callback handlers are allocated for anything else. Delegates also have the benefit of being persistent, name based (you define the target event by name, not slot or id like under OSX or GTK#). And perhaps more importantly – they are natively supported by all browsers and as thus represents a very thin layer over the actual HTML5 framework.
Future IDE advances
There are also quite a few benefits if we consider the Smart Pascal IDE. Should delegates be introduced in the form-designer, it would to a great extent remove the need for event inspection (which is a fairly complex process). You would simply add the number of events you want for an element, perhaps more than one foe the same event if that is necessary – something which would is infinitely easier to deal with.
Creating and using a delegate is almost as simple as setting an event in Delphi or Smart Mobile Studio today:
var mDelegate: TQTXDelegate; begin mDelegate:=FControl.Delegates.add; mDelegate.Bind('onClick'); mDelegate.onExecute:=Procedure (EventObj:TQTXDelegate) Begin //Handle event here end; end;
Or the short-hand version:
var mDelegate: TQTXDelegate; begin mDelegate:=FControl.Delegates.add.Bind('onClick', procedure (EventObj:TQTXDelegate) Begin //Handle event here end); end;
Triggering a delegate can now be done several ways. First, if you have access to the delegate object itself:
And secondly by name, which will only dispatch the event if it’s actually has a registered delegate(s) for that event:
begin //Trigger all delegates mapped to onClick FControl.delegates.dispatch('onClick',[0,1,"hello"]); end;
And finally you can mute events with a one-liner:
begin FControl.delegates.active:=False; end;
And last but not least, storing delegates is a piece of cake:
var mJSON: String; mAccess: IQTXPersistent; begin mAccess:=(FControl.delegates as IQTXPersistent); if assigned(mAccess) then mJSON:=mAccess.writeContent; end;
So finally we can decouple event management from the work of writing components. Such things can now be regarded almost as action objects in Delphi, specifically tailored and isolated in classes.