Archive
Delphi Developer Demo Competition votes
A month ago we setup a demo competition on Delphi Developer. It’s been a few years since we did this, and demo competitions are always fun no matter what, so it was high time we set this up!

This years prizes are awesome!
Initially we had a limit of at least 10 contestants for the competition to go through, but I will make an exception this time. The prices are great and worth a good effort. I was a bit surprised by the low number of contestants since more than 60 developers signed our poll about the event. So I was hoping for at least 20 to be honest.
I think the timing was a bit off, we are closer to the end of the year and most developers are working under deadlines. So next year I think I’ll move the date to June or July.
Be that as it may – a demo competition is a tradition by now, so we proceed to the voting process!
The contestants
The contestants this year are:
- Christian Hackbart
- Mogens Lundholm
- steven Chesser
- Jens Borrisholt
- Paul Nicholls
Note: Dennis is a moderator on Delphi Developer, as such he cannot partake in the voting process.
The code
Each contestant has submitted a project to the following repositories (in the same order as the names above), so make sure you check out each one and inspect them carefully before casting your vote.
- https://github.com/TetrisSQC/Galcon
- https://github.com/mogenslundholm/MidiAndMusicXmlPlayer
- https://github.com/jdredd87/PiDuinoDroidSystem
- https://github.com/JensBorrisholt/2048
- https://bitbucket.org/paul_nicholls/petasciifier/src
Voting
We use the poll function built-into Facebook, so just visit us at Delphi Developer to cast your vote! You can only vote once and there is a 1 week deadline on this (so votes are done on the 10th this month.
Help&Doc, documentation made easy
I have been flamed so much lately for not writing proper docs for Smart Mobile Studio, that I figured it was time to get this under wraps. Now in my defence I’m not the only one on the Smart Pascal team, sure I have the most noise, but Smart is definitely not a solo operation.
So the irony of getting flamed for lack of docs, having perpetually lobbied for docs at every meeting since 2014; well that my friend is mother nature at her finest. If you stick your neck out, she will make it her personal mission to mess you up.
So off I went in search of a good documentation system ..
The mission
My dilemma is simple: I need to find a tool that makes writing documentation simple. It has to be reliable, deal with cross chapter links, handle segments of code without ruining the formatting of the entire page – and printing must be rock solid.

Writing documentation in Open Office feels very much like this
If you are pondering why I even mention printing in this digital age, it’s because I prefer physical media. Writing a solid book, be it a mix between technical reference and user’s guide, can’t compare to a blog post. You need to let the material breathe for a couple of days between sessions to spot mistakes. I usually print things out, let it rest, then go over it with an old fashion marker.
Besides, my previous documentation suite couldn’t do PDF printing. I’m sure it could, just not around me. Whenever I picked Microsoft PDF printer as the output, it promptly committed suicide. Not even an exception, nothing, just “poff” and it terminated. The first time this happened I lost half a days work. The third time I uninstalled it, never to look back.
Another thing I would like to see, is that the program deals with graphics more efficiently than Google Docs, and at the very least more intuitively than Open Office (Oo in short). Now before you argue with me over Oo, let me just say that I’m all for Open-Office, it has a lot of great features. But in their heroic pursuit of cloning Microsoft to death, they also cloned possibly the worst layout mechanisms ever invented; namely the layout engine of Microsoft Word 2001.
Let’s just say that scaling and perspective is not the best in Open Office. Like Microsoft Word back in the day, it faithfully favours page-breaks over perspective based scaling. It will even flip the orientation if you don’t explicitly tell it not to.
Help & Doc
As far as I know, there are only two documentation suite’s on the market related with Delphi and coding. At least when it comes to producing technical manuals, help files and being written in Delphi.
First you have the older and perhaps more established Help & Manual. This is followed by the younger but equally capable Help & Doc. I ended up with the latter.
Both suite’s have more in common than similar names (which is really confusing), they offer pretty much the exact same functionality. Except Help & Doc is considerably cheaper and have a couple features that developers favour. At least I do, and I imagine the needs of other developers will be similar.
Being older, Help & Manual have worked up more infrastructure , something which can be helpful in larger organizations. But their content-management strategy is (at least to me) something of a paradox. You need more than .NET documentation and shared editing to justify the higher price -and having to install a CMS to enjoy shared editing? It might make sense if you are a publisher, ghostwriter or if you have a large department with 5+ people doing nothing but documentation; but competing against Google Documents in 2018? Sorry, I don’t see that going anywhere.
For me, Help & Doc makes more sense because it remains true to its basic role: to help you create documentation for your products. And it does that very, very well.
I also like that Help & Doc are crystal clear about their origins. Help & Manual have anonymized their marketing to tap into .Net and Java; they are not alone, quite a few companies try to hide the fact that their flagship product is written in object pascal. So you get a very different vibe from these two websites and their products.
The basics
Much like the competition, Help & Doc offers a complete WYSIWYG text editor with support for computed fields. So you can insert fields that hold variable data, like time, date (and various pieces of a full datetime), project title, author name [and so on]. I hope to see script support at some point here, so that a script could provide data during PDF/Web generation.
The editor is responsive and well written, supports tables, margins and formatting like you expect from a modern editor. Not really sure how much I need to write about a text editor, most Delphi and C++ developers have high standards and I suspect they have used RichView, which is a well-known, high quality component.
One thing I found very pleasing is that fonts are not hidden away but easily accessible; various text styles hold a prominent place under the Write tab on top of the window. This is very helpful because you don’t have to apply a style to see how it will look, you can get an idea directly from the preview.
Being able to insert conditional sections is something I found very easy. It’s no doubt part of other offerings too, but I have never really bothered to involve myself. But with so many potential targets, mobile phones, iPads, desktops, Kindle – suddenly this kind of functionality becomes a thing.
For example if you have documentation for a component, one that targets both Delphi, .NET and COM (yes people still use COM believe it or not) you don’t need 3 different copies of the same documentation – with only small variations between them. Using the conditional operations you can isolate the differences.
With Apple OSX, iOS and Android added to the compiler target (for Delphi), the need to separate Apple only instructions on how to use a library [for example], and then only include that for the Apple output is real. Windows and Linux can have their own, unique sections — and you don’t need to maintain 3 nearly similar documentation projects.
When you combine that with script support, Help & Doc is flexing some powerful muscles. I’m very much impressed and don’t regret getting this over the more expensive Help and Manual. Perhaps it would be different if I was writing casual books for a publisher, or if I made .NET components (oh the humanity!) and desperately needed to please Visual Studio. But for a hard-core Delphi and object pascal developer, Help & Doc has everything I need – and then some!
Wait, what? Script support?
Scripting docs
One of the really cool things about Help & Doc is that it supports pascal scripting. You can do some pretty amazing things with a script, and being able to iterate through the documentation in classical parent / child relationships is very helpful.

The central role of Object Pascal is not exactly hidden in Help & Doc
If you are wondering why a script engine would even be remotely interesting for an author, consider the following: you maintain 10-12 large documentation projects, and at each revision there will be plenty of small and large changes. Things like class-names getting a new name. If you have mentioned a class 300 times in each manual, changing a single name is going to be time-consuming.
This is where scripting is really cool because you can write code that literates through the documentation, chapter by chapter, section by section, paragraph by paragraph – and automatically replace all of them in a second.
I haven’t spent a huge amount of time with the scripting API Help & Doc offers yet (more busy writing), but I imagine that a plugin framework is a natural step in its evolution. I made a desktop search engine once, back between 1999 and 2005 (just after the bronze age) where we bolted Pascal Script into the system, then implemented each search engine parser as a script. This was very flexible and we could adapt to changes faster than our competitors.
While I can only speculate and hope the makers of Help & Doc reads this, creating an API that gives you a fair subset of Delphi (streams, files, string parsing et-al) that is accessible from scripts, and then defining classes for import scripts, export scripts, document processing scripts; that way developers can write their own import code to support a custom format (medical documentation springs to mind as an example). Likewise developers could write export code.
This is a part of the software I will explore more in the weeks to come!
Verdict – is it worth it?
As of writing you get Help & Doc professional at 249 €, and you can pick up the standard edition for 99€. Not exactly an earth shattering price for the mountain of work involved in creating such an elaborate system. If you factor in how much time it saves you: yes, why on earth would you even think twice!
I have yet to find a function that their competition offers that would change my mind. As a developer who is part of a small team, or even as a solo developer – documentation has to be there. I can list 10.000 reasons why Smart never got the documentation it deserves, but at least now I can scratch one of them off my list. Writing 500 A4 pages in markdown would have me throwing myself into the fjords at -35 degrees celsius.
And being the rogue that I am, should I find intolerable bugs you will be sure to hear about them — but I have nothing to complain about here.
Its one of the most pleasant pieces of software I have used in a long time.
Human beings and licenses
Before I end this article, I also want to mention that Help & Doc has a licensing system that surprised me. If you buy 2 licenses for example, you get to link that with a computer. So you have very good control over your ownership. Should you run out of licenses, well then you either have to relocate an existing license or get a new one. You are not locked out and they don’t frag you with compliance threats.

Doesn’t get much easier than this
I use VMWare a lot and sometimes forget that I’m running a clone on top of a clone, and believe me I have gotten some impressive emails in the past. I think the worst was Xamarin Mono which actually deactivated my entire environment until I called them and explained I was doing live debugging between two VMWare instances.
So very cool to see that you can re-allocate an existing license to whatever device you want without problems.
To sum up: worth every penny!
Graphics essentials in Smart Mobile Studio 3
JavaScript and the DOM has a few quirks that can be a bit tricky for Delphi developers to instinctively understand. And while our RTL covers more or less everything, I would be an idiot if I said we havent missed a spot here and there. A codebase as large as Smart is like a living canvas; And with each revision we cover more and more of our blind-spots.
Where did TW3Image.SaveToStream vanish?
We used to have a SaveToStream method in TW3Image that took the raw DIB data (raw RGBA pixel data) and emitted that to a stream. That method was never really meant to save a picture in a compliant format, but to make it easy for game developers to cache images in a buffer and quickly draw the pixel-data to a canvas (or push it to localstorage, good if you are making a paint program). This should have been made more clear in the RTL unit, but sadly it escaped me. I apologize for that.
But in this blog-post we are going to make a proper Save() function, one that saves to a proper format like PNG or JPG. It should be an interesting read for everyone.
Resources are global in scope
Before we dig in, a few words about how the browser treats resources. This is essential because the browser is a resource oriented system. Just think about it: HTML loads everything it needs separately, things like pictures, sounds, music, css styles — all these resources are loaded as the browser finds them in the code – and each have a distinct URI (uniform resource identifier) to represent them.
So no matter where in your code you are (even a different form), if you have the URI for a resource – it can be accessed. It’s important to not mix terminology here because URI is not the same as a URL. URI is a unique identifier, an URL (uniform resource location) defines “where” the browser can find something (it can also contain the actual data).
If you look at the C/C++ specs, the URL class inherits from URI. Which makes sense.
Once a resource is loaded and is assigned an URI, it can be accessed from anywhere in your code. It is global in scope and things like forms or parent controls in the RTL means nothing to the underlying DOM.
Making new resources
When you are creating new resources, like generating a picture via the canvas, that resource doesn’t have an URI. Thankfully, generating and assigning an URI so it can be accessed is very simple — and once we have that URI the user can download it via normal mechanisms.
But the really cool part is that this system isn’t just for images. It’s also for raw data! You can actually assign a URI to a buffer and make that available for download. The browsers wont care about the content.
If you open the RTL unit SmartCL.System.pas and scroll down to line 107 (or there about), you will find the following classes defined:
(* Helper class for streams, adds data encapsulation *) TAllocationHelper = class helper for TAllocation function GetObjectURL: string; procedure RevokeObjectURL(const ObjectUrl: string); end; TW3URLObject = static class public class function GetObjectURL(const Text, Encoding, ContentType, Charset: string): string; overload; class function GetObjectURL(const Text: string): string; overload; class function GetObjectURL(const Stream: TStream): string; overload; class function GetObjectURL(const Data: TAllocation): string; overload; class procedure RevokeObjectURL(const ObjectUrl: string); // This cause a download in the browser of an object-url class procedure Download(const ObjectURL: string; Filename: string); overload; class procedure Download(const ObjectURL: string; Filename: string; const OnStarted: TProcedureRefS); overload; end;
The first class, TAllocationHelper, is just a helper for a class called TAllocation. TAllocation is the base-class for objects that allocate raw memory, and can be found in the unit System.Memory.Allocation.pas.
TAllocation is really central and more familiar classes like TMemoryStream expose this as a property. The idea here being that if you have a memory stream with something, making the data downloadable is a snap.
Hopefully you have gotten to know the central buffer class, TBinaryData, which is defined in System.Memory.Buffer. This is just as important as TMemoryStream and will make your life a lot easier when talking to JS libraries that expects an untyped buffer handle (for example) or a blob (more on that later).
The next class, TW3URLObject, is the one that is of most interest here. You have probably guessed that TAllocationHelper makes it a snap to generate URI’s for any class that inherits from or expose a TAllocation instance (read: really handy for TMemoryStream). But TW3URLObject is the class you want.
The class contains 3 methods with various overloading:
- GetObjectURL
- RevokeObjectURL
- Download
I think these are self explanatory, but in short they deliver the following:
- GetObjectURL creates an URI for a resource
- RevokeObjectURL removes a previously made URI from a resource
- Download triggers the “SaveAs” dialog so users can, well, save the data to their local disk
The good news for graphics is that the canvas object contains a neat method that does this automatically, namely the ToDataUrl() function, which is a wrapper for the raw JS canvas method with the same name. Not only will it encode your picture in a normal picture format (defaults to png but supports all known web formats), it will also return the entire image as a URI encoded string.
This saves us the work of having to manually call GetObjectURL() and then invoke the save dialog.
Making some offscreen graphics
TW3Image is not meant for drawing, it’s like Delphi’s TImage and is a graphics container. So before we put a TW3Image on our form we are going to create the actual graphics to display. And we do this by creating an off-screen graphics context, assign a canvas to it, draw the graphics, and then encode the data via ToDataUrl().
To make things easier, lets use the Delphi compatible TBitmap and TCanvas classes. These can be found in SmartCL.Legacy. They are as compatible as I could make them.
- Browsers only support 32 bit graphics, so only pf32bit is allowed
- I havent implemented checkered, diagonal or other patterns – so bsSolid and bsClear are the only brush modes for canvas (and pen style as well).
- Brush doesn’t have a picture property (yet), but this will be added later at some point. I have to replace the built-in linedraw() method with the Bresham algorithm for that to happen (and all the other primitives).
- When drawing lines you have to call Stroke() to render. The canvas buffers up all the drawing operations and removes overlapping pixels to speed up the final drawing process — this is demanded by the browser sadly.
Right, with that behind us, lets create an off-screen bitmap, fill the background red and assign it to a TW3Image control.
To replicate this example please use the following recipy:
- Start a new “visual components project”
- Add the following units to the uses clause:
- System.Colors
- System.Types.Graphics
- SmartCL.Legacy
- Add a TW3Button to the form
- add a TW3Image to the form
- Save your project
- Double-Click on the button. This creates a code entry point for the default event, which for a button is OnClick.
Let’s populate the entry point with the following:
procedure TForm1.W3Button1Click(Sender: TObject); var LBitmap: TBitmap; LRect: TRect; begin LBitmap := TBitmap.Create; try LBitmap.Allocate(640, 480); LRect := TRect.Create(0, 0, LBitmap.width-1, LBitmap.Height-1); LBitmap.Canvas.Brush.Color := clRed; LBitmap.Canvas.FillRect(LRect); w3image1.LoadFromUrl( LBitmap.Canvas.ToDataURL('image/png') ); finally LBitmap.free; end; end;
The code above creates a bitmap, which is an off-screen (not visible) graphics context. We then set a background color to use (red) and fill the bitmap with that color. When this is done we load the picture-data directly into our TW3Image control so we can see it.
Triggering a download
With the code for creating graphics done, we now move on to the save mechanism. We want to download the picture when the user clicks the button.
Since the image already have an URI, which it get’s when you call the ToDataURL() method, we don’t need to mess around with blob buffers and generating the URI manually. So forcing a download could not be simpler:
procedure TForm1.W3Button1Click(Sender: TObject); var LBitmap: TBitmap; LRect: TRect; begin LBitmap := TBitmap.Create; try LBitmap.Allocate(640, 480); LRect := TRect.Create(0, 0, LBitmap.width-1, LBitmap.Height-1); LBitmap.Canvas.Brush.Color := clRed; LBitmap.Canvas.FillRect(LRect); var LEncodedData:= LBitmap.Canvas.ToDataURL('image/png'); w3image1.LoadFromUrl(LEncodedData); TW3URLObject.Download( LEncodedData, 'picture.png'); finally LBitmap.free; end; end;
Note: The built-in browser in Smart doesn’t allow save dialogs, so when you run this example remember to click the “open in browser” button on the execute window. Then click the button and voila — the image is downloaded directly.
Well, I hope this has helped! I will do a couple of more posts on graphics shortly because there really is a ton of cool features here. We picked heavily from various libraries when we implemented TW3Canvas and TCanvas, so if you like making games or display data – then you are in for a treat!
Power for pennies, getting a server rack and preparing my ultimate coding environment
One of the benefits of doing repairs on your house, is that during the cleanup process you come over stuff you had completely forgot about. Like two very powerful Apple blade servers (x86) I received as a present three years ago. I never got around to using them because I there was literally no room in my house for a rack cabinet.
Sure, a medium model rack cabinet isn’t that big (the size of a cabin refrigerator), but you also have to factor in that servers are a lot more noisy than desktop PCs; the older they are the more noise they make. So unless you have a good spot to place the cabinet, where the noise wont make it unbearable to be around, I suggest you just rent a virtual instance at Amazon or something. It really depends on how much service coding you do, if you need to do dedicated server and protocol stress testing (the list goes on).
Power for pennies

Sellers photo. It needs a good clean, but this kit would have set you back $5000 a decade ago; so picking this up for $400 is almost ridicules.
The price of such cabinets (when buying new ones) can be anything from $800 to $5000 depending on the capacity, features and materials. My needs for a personal server farm are more than covered by a medium cabinet. If it wasnt for my VMWare needs I would say it was overkill. But some of my work, especially with node.js and Delphi system services that should handle terabytes of raw data reliably 24/7, that demands a hard-core testing environment.
Having stumbled upon my blade servers I decided to check the local second-hand online forum; and I was lucky enough to find (drumroll) a second-hand cabinet holding a total of 10 blades for $400. So I’ll be picking up this beauty next weekend. It will be so good to finally get my blades organized. Not to mention all my SBC / Node.js cluster experiments centralized in one physical location. Far away from my home office space (!)
Interestingly, it comes fitted with 3 older servers. There are two Dell web and file servers, and then a third, unmarked mystery box (i3 cpu + sata caddies so that sounds good).
It really is amazing how much cpu fire-power you can pick up for practically nothing these days. $50 buys you a SBC (single board computer) that will rival a Pentium. $400 buys you a 10 blade cabinet and 3 servers that once powered a national newspaper (!).
VMWare delights
All the blades I have mentioned so far are older models. They are still powerful machines, way more than $400 livingroom NAS would get you. So my node.js clustering will run like a dream and I will be able to host all my Delphi development environments via VMware. Which brings us neatly to the blade I am really looking forward to get into the rack.
I bought an empty server blade case back in 2015. It takes a PSU, motherboard, fans and everything else is there (even the six caddies for disks). Into this seemingly worthless metal box I put a second generation Intel i7 monster (Asus motherboard), with 32 gigabyte ram – and fitted it with a sexy NVidia GEFORCE GTX 1080 TI.

All my Delphi work, Smart work and various legacy projects I maintain, all in one neat rack
This little monster (actually it takes up 2 blade-spots) allows me to run VMWare server, which gives me at least 10 instances of Windows (or Linux, or OSX) at the same time. It will also be able to host and manage roughly 1000 active Smart Desktop users (the bottleneck will be the disk and network more than actual computation).
Being a coder in 2018 is just fantastic!
Things we could only dream about a decade ago can now be picked up for close to nothing (compared to the original cost). Just awesome!
Smart Pascal file enumeration under node.js
Ok. I admit it. Writing an RTL from scratch has been one of the hardest tasks I have ever undertaken. Thankfully I have not been alone, but since I am the lead developer for the RTL, it naturally falls on me to keep track of the thousands of classes it comprises; how each affect the next, the many inheritance chains and subsequent causality timelines that each namespace represents.
We were the first company in the world to do this, to establish the compiler technology and then author a full RTL on top of that – designed to wrap and run on top of the JavaScript virtual machine. To be blunt, we didn’t have the luxury to looking at what others had done before us. For every challenge we have had to come up with solutions ourselves.
Be that as it may, after seven years we have gotten quite good at framework architecture. So whenever we need to deal with a new runtime environment such as node.js – we have already built up a lot of experience with async JSVM development, so we are able to absorb and adapt much faster than our competitors.
Digging into a new platform
Whenever I learn a new language, I typically make a little list of “how do I do this?” type questions. It can be simple, like writing text to stdout, or more elaborate like memory mapped files, inheritance model, raw memory access and similar topics.
But one of the questions have always been: how do I enumerate files in a folder?
While this question is trivial at best, it stabs at the heart of the sub structure of any language. On operating systems like Linux a file is not just data on a disk like we are used to from Windows. A file can be a socket, a virtual access point exposed by the kernel, a domain link, a symbolic link or a stream. So my simple question is actually motivated to expose the depth of the language im learning. I then write down whatever topics come up and then research / experiment on them separately.
Node, like the browser, executes code asynchronously. This means that the code you write cannot be blocking (note: node does support synchronous file IO methods, but you really don’t want to use them in a server. They are typically used before the server is started to load preferences files and data).
As you can imagine, this throws conventional coding out the window. Node exposes a single function that returns an array of filenames (array of string), which helps, but it tells you nothing about the files. You don’t get the size, the type, create and modify timestamps – just the names.
To get the information I just mentioned you have to call a function called “fs.stat”. This is a common POSIX filesystem command. But again we face the fact that everything is async, so that “for / next” loop is useless.
Luke Filewalker
In version 3.0 of Smart Mobile Studio our Node.JS namespace (collection of units with code) has been upgraded and expanded considerably. We have thrown out almost all our older dependencies (like utf8.js and base64.js) and implemented these as proper codec classes in Smart Pascal directly.
Our websocket framework has been re-written from scratch. We threw out the now outdated websocket-io and instead use the standard “ws” framework that is the most popular and actively maintained module on NPM.
We have also implemented the same storage-device class that is available in the browser, so that you can write file-io code that works the same both server-side and client-side. The changes are in the hundreds so I wont iterate through them all here, they will be listed in detail on the release-notes document when the time comes.
But what is a server without a fast, reliable way of enumerating files?
Well, here at the Smart Company we use our own products. So when writing servers and node micro-services we face the exact same challenges as our customers would. Our job is to write ready solutions for these problems, so that you don’t have to spend days and weeks re-inventing the wheel.
Enumerating files is handled by the class TNJFileWalker (I was so tempted to call it Luke). This takes care of everything for you, all the nitty-gritty is neatly packed into a single, easy to use class.
Here is an example:

Enumerating files has literally been reduced to childs play
The class also expose the events you would expect, including a filtering event where you can validate if a file should be included in the final result. You can even control the dispatching speed (or delay between item processing) which is helpful for payload balancing. If you have 100 active users all scanning their files at the same time -you probably want to give node the chance to breathe (20ms is a good value).
The interface for the class is equally elegant and easy to understand:

What would you prefer to maintain? 500.000 lines of JavaScript or 20.000 lines of pascal?
Compare that to some of the spaghetti JavaScript developers have to live with just to perform a file-walk and then do a recursive “delete folder”. Sure hope they check for “/” so they don’t kill the filesystem root by accident.
const fs = require('fs'); const path = require('path'); function filewalker(dir, done) { let results = []; fs.readdir(dir, function(err, list) { if (err) return done(err); var pending = list.length; if (!pending) return done(null, results); list.forEach(function(file){ file = path.resolve(dir, file); fs.stat(file, function(err, stat){ // If directory, execute a recursive call if (stat && stat.isDirectory()) { // Add directory to array [comment if you need to remove the directories from the array] results.push(file); filewalker(file, function(err, res){ results = results.concat(res); if (!--pending) done(null, results); }); } else { results.push(file); if (!--pending) done(null, results); } }); }); }); }; function deleteFile(dir, file) { return new Promise(function (resolve, reject) { var filePath = path.join(dir, file); fs.lstat(filePath, function (err, stats) { if (err) { return reject(err); } if (stats.isDirectory()) { resolve(deleteDirectory(filePath)); } else { fs.unlink(filePath, function (err) { if (err) { return reject(err); } resolve(); }); } }); }); }; function deleteDirectory(dir) { return new Promise(function (resolve, reject) { fs.access(dir, function (err) { if (err) { return reject(err); } fs.readdir(dir, function (err, files) { if (err) { return reject(err); } Promise.all(files.map(function (file) { return deleteFile(dir, file); })).then(function () { fs.rmdir(dir, function (err) { if (err) { return reject(err); } resolve(); }); }).catch(reject); }); }); }); };
Writing Smart Pascal Controls, async initialization and the tao pattern
Async programming can take a bit getting used to if you come straight from Delphi or Lazarus. So in this little article I am going to show you an initialization pattern that will help you initialize your custom-controls and forms in way that is reliable.
Object Ready
In 99.9% of the custom-controls you create, you will either inherit directly from an existing control (like TW3Button, TW3EditBox or other traditional visual controls), or directly from TW3CustomControl.
If you have a quick look at the source for the RTL, which we take for granted that you do, you will find that our RTL is very familiar. It is loosely based on the LCL (lazarus component library), VCL (Visual component library) and with a dash of Mono GTK# thrown in for good measure. But while familiar in appearance, it really is a completely new RTL written to deliver the best of what HTML5 / JS has to offer.
One of the more interesting methods of TW3CustomControl is ObjectReady. This is actually introduced further down in the inheritance chain with TW3MovableControl, but most developers want the infrastructure TW3CustomControl delivers – so that will be the focus on the topic today.
In short, ObjectReady is called when your visual control has been created, injected into the DOM and is ready for use.
The common mistake
A common mistake with ObjectReady() is that the ready state somehow covers any child elements you might have created for your control. This is not the case. ObjectReady() is called when the current control is finished with its initialization, and is ready for manipulation.
Just before the ObjectReady() method is called, the csReady flag is added to the ComponentState set (note: if you don’t know what a set is, it’s a bit like an array of enums. Please google “Delphi sets” to investigate this further if you are just starting out).
Checking if a control is ready can be done manually by reading the csReady state from a controls ComponentState. But naturally, that only works if the control has already reached that state. Prior to the ready state the csCreating state is added to ComponentState, this is removed as the initialization completes and the control enters ready state.
The united states of custom-controls
To better understand when the different component states are set and what really happens when you create a visual control, let’s go through the steps one by one.
- TW3TagObj
- Ordinary constructor (create) is called
- csCreating is added to ComponentState
- DOM element name to be managed is obtained via TW3TagObj.MakeElementTagId()
- Handle is obtained via TW3TagObj.MakeElementTagObj()
- csLoading in added to ComponentState
- A DOM level identifier (name) is assigned to the control
- ZIndex is calculated and assigned to the control
- StyleTagObject() method is called for any css adjustments
- InitializeObject() is called, this is the constructor in our RTL
- Control instance is registered with the global control tracker
- csCreating is removed from ComponentState
- csLoading in removed from ComponentState
- Ordinary constructor (create) is called
- TW3MovableControl
- Alpha blending is initialized but not activated
- if cfIgnoreReadyState is set in CreationFlags() then ObjectReady is called immediately without any delay
- If not cfIgnoreReadyState is set, the ReadySync() method is called
the ReadySync() method is of special importance here.
Since JavaScript is asynchronous, reality is that whatever child controls you have created during InitializeObject, can still be under construction even after InitializeObject() finishes. The JavaScript engine might have returned a handle, but the data for the instance is still under construction behind the scenes.
To be blunt: Never trust JavaScript to deliver a 100% ready to use element. If the browser is under heavy stress from other websites and internal work, that can have catastrophic consequences on the state of the objects it returns.
This is one of many reasons that made us chose to write our RTL from scratch rather than just fork CLX or try to be as Delphi friendly as possible. That would have been much easier for us, but it would also be to sell you on the tooth-fairy because that’s not how JavaScript works.
We want our users to have full control and enjoy the same freedom and simplicity that made us fall in love with object pascal all those years ago. And if we forced JavaScript into a pre-fabricated mold like the LCL; the spark and flamboyance that JavaScript brings to the table would have been irreparably damaged if not lost.
But let’s get back on topic.
Like mentioned above, ReSync() is of special importance. It will continuously check if the control is “ready” on a 10ms interval, and it keeps going until the criteria matches or it times out. To avoid infinite loops it has a maximum call stack of 300. Meaning it will keep trying 300 times, a total of 3 seconds and then break out free for safety reasons.
But once the criteria for ready-state matches (or the waiting interval times out) – ObjectReady() is finally called.
Keep your kids in order
While knowing when the control is ready for us is great for writing components, what practical purpose does it really serve if the child controls is excluded?
Well, again we are back at freedom. We could have baked in a wait sequence for our forms (since the designer knows what child elements are involved). But sadly that wont work on custom controls that the IDE doesn’t manage. And it would only work on forms.
A negative side-effect of this (yet I did test it) is that a form will remain blank until all child controls, their children and their grand children – all reports “ready”.
In short: our code cannot manage what it doesn’t know. The IDE cannot (for reasons obvious) know what your code creates at runtime. And in large and complex controls like grids, planners or MDI systems – such code would get in your way and render the benefits null and void quickly.
As of writing there are some creative solutions to this, trying to get the timing right
- Write your own checking routines inspired by ReadySync
- Ignore the whole thing and just check ready-state and that child elements are not NIL in Resize(). This is what most people do.
- Use TW3Dispatch and throw in an extra Resize() call somewhere in ObjectReady()
While perfectly legal (or perhaps better said: not illegal), these solutions are not very reliable. If the browser is under stress it can prioritize your layout code as less important – and suddenly you have a button where it’s not supposed to be, or a panel that never stretched as planned.
The Tao pattern
Tao (time aware operation) is pattern I created to solve this problem with a bit of grace. Much like the ReadySync() method we talked about earlier, it performs interval based checking of child element states, and thus allows you to do operations in a timely fashion.
As you probably know, under Smart Pascal you are not supposed to override the constructor when you create new controls. Instead you override InitializeObject(). The same goes for the destructor, there you override FinalizeObject().
So the 5 “must-know” methods for writing your own controls are:
- InitializeObject
- FinalizeObject
- ObjectReady
- Resize
- StyleTagObject
Note: Since Smart Mobile Studio has an evolved theme engine, it is rare that people override StyleTagObject() these days. But there are cases where you want to set some HTML attribute or alter a style; changes that are too small to justify a new style in the global stylesheet. It’s also the place to call ThemeReset() if you don’t want your control to use themes at all, or perhaps set a different theme border and background.
OK, let’s look at a practical example of how TAO works. It is simple, flexible and requires minimal adaptation if you want to adjust older controls you have made.
In this example we will be making a path selector. This is essentially an edit box with a button situated at the far-right. Clicking the button would bring up some form of dialog. I am excluding that for brevity since it’s not the control that is interesting here, but rather how we initialize the control.
type TTaoControl = class(TW3CustomControl) private FButton: TW3Button; FEdit: TW3EditBox; protected procedure InitializeObject; override; procedure FinalizeObject; override; procedure ObjectReady; override; procedure StyleTagObject; override; procedure Resize; override; end;
As you can see the control class is defined exactly the same way as before. There is no change what so ever in how you write your classes. Now let’s look at the implementation:
procedure TTaoControl.InitializeObject; begin inherited; TransparentEvents := false; SimulateMouseEvents := false; // Create our editbox FEdit := TW3EditBox.Create(self); FEdit.SetSize(80, 28); // reate our select button FButton := TW3Button.Create(self); FButton.SetSize(70, 28); end; procedure TTaoControl.FinalizeObject; begin FEdit.free; FButton.free; inherited; end; procedure TTaoControl.ObjectReady; begin inherited; // set some constraints (optional) Constraints.MinWidth := 120; Constraints.MinHeight := 32; Constraints.Enabled := true; // TAO: Wait for the child controls to reach ready-state TW3Dispatch.WaitFor([FEdit, FButton], 5, procedure (Success: boolean) begin if Success then begin // set some properties for the edit box FEdit.ReadOnly := true; FEdit.PlaceHolder := 'Please selected a file'; // set caption for button FButton.Caption := 'Select'; // Do an immediate resize Resize(); end; end); end; procedure TTaoControl.StyleTagObject; begin inherited; // Set a container border. This border is // typically used by TW3Panel and TW3GroupBox ThemeBorder := btContainerBorder; end; procedure TTaoControl.Resize; var LBounds: TRect; dx, dy: integer; wd, EditWidth: integer; begin inherited; // Make sure we dont do anything if resize has been // called while the control is being destroyed if not (csDestroying in ComponentState) then begin // Make sure we have ready state if (csReady in ComponentState) then begin // Check that child elements are all assigned // and that they have their csReady flag set in // ComponentState. This can be taxing. A more lightweight // version is TW3Dispatch.Assigned() that doesnt check // the ready state (see class declaration for more info) if TW3Dispatch.AssignedAndReady([FButton, FEdit]) then begin // Finally: layout the controls. This can be // optimized quite a bit, but focus is not on // layout code, but rather the sequence in which operations // are executed and handled. LBounds := ClientRect; wd := LBounds.width; dy := (LBounds.Height div 2) - (FEdit.Height div 2); EditWidth := (wd - FButton.Width) - 4; FEdit.SetBounds(LBounds.left, dy, EditWidth, FEdit.Height); dx := LBounds.left + EditWidth + 2; dy := (LBounds.Height div 2) - (FButton.Height div 2); FButton.SetBounds(dx, dy, FButton.Width, FButton.Height); end; end; end; end;
If you look closely, what we do here is essentially to spread the payload and cost of creating child elements over multiple methods.
We reduce the constructor, InitializeObject(), to just creating our child controls and setting some initial sizes. This last point, setting initial size, is actually important. Because if the control has no size (width = 0, or height = 0) the browser will not treat the element as visible. Which in turn causes TW3Dispatch.WaitFor() to wait until a size is set.
TW3Dispatch methods
TW3Dispatch is a partial class. This is something that neither Delphi or Freepascal supports, and it has it’s root in C# and the dot net framework.
In short it means that a class can have it’s implementation spread over multiple files. So instead of having to complete a class in a single unit, or inherit from a class and then expanding it – partial classes allows you to expand a class over many units.
This is actually really cool and useful, especially when you work with multiple targets. For example, TW3Dispatch is first defined in System.Time.pas which is the universal namespace that only contains code that runs everywhere. This gives you the basic functionality like delayed execution (just open the unit and have a look).
The class is then further expanded in SmartCL.Time (SmartCL being the namespace for visual, HTML based JavaScript applications). There it gains methods like RequestAnimationFrame() which doesnt exist under node.js for example.
TW3Dispatch is further expanded in SmartCL.Components.pas, which is the core unit for visual controls. So starting with version 3.0 the functions I have just demonstrated will be available in the RTL itself.
Until then, you can download TW3Dispatch with the TAO methods here. You need to put it in your own unit, and naturally – use it with care.
Click here to download the TW3Dispatch code.
Note: This code is not free or open-source. It is indended for Smart Mobile Studio owners exclusively, and made available here so registered users can start working with the control coding pattern.
Using Smart Mobile Studio under Linux
Every now and then when I post something about Smart Mobile Studio, an individual or two wants to inform me how they cannot use Smart because it’s not available for Linux. While more rare, the same experience happens now and then with OS X.
While the request for Linux or OS X support is both valid and understandable (and something we take seriously), more often than not these questions can be a pre-cursor to a larger picture; one that touches on open-source, pricing and personal philosophical points of view; often with remarks on pricing.
Truth be told, the price we ask for Smart Mobile Studio is close to symbolic. Especially if you take the time to look at the body of work Smart delivers. We are talking hundreds of hand written units with thousands of classes, each spesifically adapted for HTML5, Phonegap and Node.js. Not to mention ports of popular JavaScript frameworks.
If you compare this to native object pascal development tools with similar functionality, they can set you back thousands of dollars. Our asking price of $149 for the pro edition, $399 for the enterprise edition, and a symbolic $42 for the basic edition, that is an affordable solution. Also keep in mind that this gives you access to updates for a duration of 12 months. When was the last time you bought a full development suite that allows you to write mobile applications, platform independent servers, platform independent system services and HTML5 web applications for less that $400 ?

Our price model is more than reasonable considering what you get
With platform independent we mean that in the true sense of the word: once compiled, no changes are required. You can write a system service on Windows and it will run just fine under Linux or OS X. No re-compile needed. You can take a server and copy it to Amazon or Azure, run it in a cluster or scale it from a single instance to 100 instances without any change. That is unheard of for object pascal until now.
Smart Mobile Studio is the only object pascal development system that delivers a stand-alone IDE, stand-alone compiler, a wast object-oriented run-time library written from scratch to cover HTML5, Node.js and embedded systems that run JavaScript.
And yes, we know there are other systems in circulation, but none of them are even close to the functionality that we deliver. Functionality that has been polished for seven years now. And our RTL is growing every day to capture and expose more and more advanced functionality that you can use to enrich your products.

The RTL class browser shows the depth of our RTL
As of writing we have a team of six people working on Smart Mobile Studio. We have things in our labs that is going to change the way people build applications forever. We were the first to venture into this new landscape. There were nobody we could imitate, draw inspiration from or learn from. We had to literally make the path as we moved forward.
And our vision and goal remains the same today as it was seven years ago: to empower object pascal developers – and to secure their investment in the language and methodology that is object pascal.
Discipline and purpose
There is so much I would like to work on right now. Things I want to add to Smart Mobile Studio because I find them interesting, powerful and I know people are going to love them. But that style of development, the “Garage days” as people call it, is over. It does wonders in the beginning of a project maybe, but eventually you reach a stage where a formal timeline and business plan must be carved in stone.
And once defined, you have to stick to it. It would be an insult to our customers if we pivoted left and right on a whim. Like every company we have room for research, even a couple of skunkwork projects, but our primary focus is to make our foundation rock solid before further growth.

By tapping into established JavaScript frameworks you can cover more than 40+ embedded systems and micro-controllers. More and more hardware supports JS for automation
Our “garage days” ended around three years ago, and through hard work we defined our timeline, business model and investor program. In 2017 we secured enough capital to continue full-time development.
Our timeline has been published earlier, but we can re-visit some core points here:
The visual components that shipped with Smart Mobile Studio in the beginning, were meant more as examples than actual ready-to-use modules. This was common for other development platforms of the day, such as Xamarin’s C# / Mono toolchain, where you were expected to inherit from and implement aspects of a “partial class”. This is also why Smart Pascal has support for partial classes (neither Delphi or Freepascal supports this wonderful feature).

One of our skunkwork projects is a custom linux distro that runs your Smart applications directly in the Linux framebuffer. No X or desktop, just your code. Here running “the smart desktop” as the only visual front-end under x86 vmware
Since developers coming from Delphi had different expectations, there was only one thing to do. To completely re-write every single visual control (and add a few new controls) so that they matched our customers expectations. So the first stretch of our timeline has been 100% dedicated to the visual aspects of our RTL. While doing so we have made the RTL faster, more efficient, and added some powerful sub-systems:
- A dedicated theme engine
- Unified event delegation
- Storage device classes
- Focus and control tracking
- Support for relative position modes
- Support for all boxing models
- Inline linking ( {$R “file.js”} will now statically link an external library)
- And much, much more
So the past eight months has been all about visual components.

Theming is important
The second stretch, which we are in right now, is dedicated to the non-visual infrastructure. This means in particular Node.js but also touches on non-visual components, TAction support and things that will appear in updates this year.
Node.js is especially important since it allows you to write platform and chipset independent web servers, system services and command-line applications. This is pioneering work and we are the first to take this road. We have successfully tamed the alien landscape of JavaScript, both for client, mobile and server – and terraformed it into a familiar, safe and productive environment for object pascal developers.
I feel the results speak for themselves, and our next update brings Smart Mobile Studio to the next level: full stack cloud and web development. We now cover back-end, middle-ware and front-end technologies. And our RTL now stretches from micro-controllers to mobile application to clustered cloud services.
This is the same technology used by Netflix to process terabytes of data every second on a global scale. Which should tell you something about the potential involved.
Working on Linux
Since Smart Mobile Studio was designed to be a swiss army knife for Delphi and Lazarus developers, capable to reaching segments of the market where native code is unsuitable – our primary focus is Microsoft Windows. At least for now.
Delphi itself is a Windows-based development system, and even though it supports multiple targets, Windows is still the bread and butter of commercial software development.
Like I mentioned above, we have a timeline to follow, and until we have reached the end of that line, we are not prepared to refactor our IDE for Linux or OS X. This might change sooner than people think, but until our timeline for the RTL is concluded, we will not allocate time for making the IDE platform independent.
But, you can actually run Smart Mobile Studio on both Linux and OS X today.
Linux has a system called Wine. This is a system that implements the Windows API, but delegates all the calls to Linux. So when a Windows program calls a WinAPI through Wine, its delegated to Linux variation of the same call. This is a massive undertaking, but it has years of work behind it and functions extremely well.
So on linux you can install it by opening up a shell and typing:
sudo apt-get install wine
I take for granted here that your Linux flavour has aperture installed (I’m using Ubuntu since that is easy to work with), which is the package manager that gives you the “apt-get” command. If you have some other system then just google how to install a package.
With Wine and it’s dependencies installed, you can run the Smart Mobile Studio installer. Wine will create a virtual, sandboxed disk for you – so that all the files end up where they should. Once finished you punch in the license serial number as normal, and voila – you can now use Smart Mobile Studio on Linux.
Note: in some cases you have to right-click the SmartMS.exe and select “run with -> Wine”, but usually you can just double-click the exe file and it runs.
Smart Mobile Studio on OSX
Wine has been ported to OS X, but it’s more user friendly. You download a program called wine-bottler, which takes Smart and bundles it with wine + any dependencies it needs. You can then start Smart Mobile Studio like it was a normal OS X application.
Themes and look
The only problem with Wine is that it doesnt support Windows themes out of the box. It would be illegal for them to ship those files. But you can manually copy over the windows theme files and install them via the Wine config application. Once installed, Smart will look as it should.
By default the old Windows 95 look & feel is used by Wine. Personally I dont care too much about this, it’s being able to code, compile and run the applications that matters to me – but if you want a more modern look then just copy over the Windows theme files and you are all set.
Multiplication decomposer
Here is a fun little number decomposer I made a while back. As you might know, the ancient egyptians were no strangers to binary. They also didnt use multiplication tables like we do – but instead used a method called “double down”.
To demonstrate this technique I wrote a simple little program that takes a multiplication and then breaks it down to the numbers an egyptian would look-up in his table to find the right answere.

It’s actually pretty cool. They did not apply multiplication like we do at all, but adding
You will need to drop two textboxes, 3 labels, one button and a memo control on your form (see layout in picture).
unit Form1; interface uses System.Types, System.Types.Convert, System.Objects, System.Time, SmartCL.System, SmartCL.Time, SmartCL.Graphics, SmartCL.Components, SmartCL.FileUtils, SmartCL.Forms, SmartCL.Fonts, SmartCL.Theme, SmartCL.Borders, SmartCL.Application, SmartCL.Controls.Button, SmartCL.Controls.Label, SmartCL.Controls.EditBox, SmartCL.Controls.Memo; type TDecomposer = Class(TObject) private FBitValues: TIntArray; FLeftPillar: TIntArray; FRightPillar: TIntArray; FSumPillar: TIntArray; protected procedure BuildLeftPillar(Number:Integer); procedure BuildRightPillar(Multiplier:Integer); public Property LeftPillar:TIntArray read FLeftPillar; Property RightPillar:TIntArray read FRightPillar; Property SumPillar:TIntArray read FSumPillar; function DecomposeNumber(aNumber:Integer):String; function DecomposeMultiplication(aNumber,aMultiplier:Integer):String; Constructor Create;Virtual; end; TForm1 = class(TW3Form) procedure W3Button1Click(Sender: TObject); private {$I 'Form1:intf'} protected procedure InitializeForm; override; procedure InitializeObject; override; procedure Resize; override; end; implementation { TForm1 } procedure TForm1.W3Button1Click(Sender: TObject); begin var LObj := TDecomposer.Create; try var LText := LObj.DecomposeMultiplication(StrToInt(w3editbox1.Text),StrToInt(w3editbox2.text)); w3memo1.text := LText; writeln(LText); finally LObj.free; end; end; procedure TForm1.InitializeForm; begin inherited; // this is a good place to initialize components end; procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} end; procedure TForm1.Resize; begin inherited; end; //############################################################################# // TDecomposer //############################################################################# constructor TDecomposer.Create; begin inherited Create; (* Build table of bitvalues *) var mValue := 1; for var x :=1 to 32 do begin FBitValues.add(mValue); mValue:=mValue * 2; end; end; procedure TDecomposer.BuildLeftPillar(Number:Integer); begin FLeftPillar.clear; if FBitValues.length>0 then begin var mValue := 1; for var x := FBitValues.low to FBitValues.high do begin if FBitValues[x] <= Number then FLeftPillar.add(FBitValues[x]) else break; end; end; end; procedure TDecomposer.BuildRightPillar(Multiplier:Integer); begin FRightPillar.clear; if FLeftPillar.length>0 then begin for var x := FLeftPillar.low to FLeftPillar.high do begin FRightPillar.add(Multiplier); Multiplier:=Multiplier * 2; end; end; end; function TDecomposer.DecomposeMultiplication (aNumber,aMultiplier:Integer):String; begin var mSum := aNumber * aMultiplier; BuildRightPillar(aMultiplier); result := aNumber.toString + ' x ' + aMultiplier.toString + ' = ' + DecomposeNumber(mSum); end; function TDecomposer.DecomposeNumber(aNumber:Integer):String; begin FSumpillar.clear; FLeftPillar.clear; FRightPillar.clear; BuildLeftPillar(aNumber); for var x := FLeftPillar.low to FLeftPillar.High do begin if TInteger.getBit(x,aNumber) then FSumPillar.add(FBitValues[x]); end; if FSumPillar.length>0 then Begin result:=aNumber.ToString + ' = '; for var x:=FSumPillar.low to FSumpillar.high do begin if x=FSumPillar.low then result += FSumPillar[x].toString else result += ' + ' + FSumPillar[x].toString; end; end; end; function QTX_GetNumberProducer(aNumber:Integer):String; const QTX_BITS: Array[0..31] of Integer = ( 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, 2097152, 4194304, 8388608, 16777216, 33554432, 67108864, 134217728, 268435456, 536870912, 1073741824, 2147483648); Begin var LStack: array of string; if aNumber > 0 then begin for var x := QTX_BITS.low to QTX_BITS.high do begin if TInteger.getBit(x,aNumber) then LStack.add(QTX_BITS[x].toString); if QTX_BITS[x] >= aNumber then break; end; if LStack.length>0 then begin result := aNumber.toString + ' = '; for var x := LStack.low to LStack.high do begin if x > LStack.low then result += ' + ' + LStack[x] else result += LStack[x]; end; end; end else result := "0"; end; function QTX_GetNumberMultiplier(aFirst,aSecond:Integer):String; Begin var LSum := aFirst * aSecond; result := aFirst.ToString() + ' x ' + aSecond.ToString(); result += ' = '; result += QTX_GetNumberProducer(LSum); end; initialization Forms.RegisterForm({$I %FILE%}, TForm1); end.
Smart Mobile Studio 3.0 and beyond
With Smart Mobile Studio 3.0 entering its second beta, Smart Pascal developers are set for a boost in quality, creativity and power. We have worked extremely hard on the product this past year, including a complete rewrite of all our visual controls (and I mean all). We also introduced a completely new theme engine, one that completely de-couples visual appearance from structural architecture (it also allows scripting inside the CSS theme files).
All of that could be enough for a version bump, but we didn’t stop there. Much of the sub-strata in Smart has been re-implemented. Focus has been on stability, speed and future growth. The system is now divided into a set of name-spaces (System, SmartCL, SmartNJ, Phonegap, and Espruino), making it easier to navigate between the units as well as expanding the codebase in the future.
To better understand the namespaces and why this is a good idea, let’s go through how our units are organized.
- The System namespace is the foundation. It contains clean, platform independent code. Meaning code that doesn’t rely on the DOM (browser) or runtime (node). Focus here is on universal code, and to establish common object-pascal classes.
- Our SmartCL namespace contains visual code, meaning code and controls that targets the browser and the DOM. SmartCL rests on the System namespace and draws functionality from it. Through partial classes we also expand classes introduced in the system namespace. A good example is System.Time.pas and SmartCL.Time.pas. The latter expands the class TW3Dispatch with functionality that will only work in the DOM.
- SmartNJ is our high-level nodejs namespace. Here you find classes with fairly complex behavior such as servers, memory buffers, processes and auxillary classes. SmartNJ draws from the system namespace just like SmartCL. This was done to avoid multiple implementations of streams, utility classes and common functions. Being able to enjoy the same functionality under all platforms is a very powerful thing.
- Phonegap is our namespace for mobile devices. A mobile application is basically a normal visual application using SmartCL, but where you access extra functionality through phonegap. Things like access to a device’s photos, filesystem, dialogs and so on is all delegated via phonegap.
- Espruino is a namespace for working with Espruino micro-controllers. This has been a very low-level affair so far, due to size limitation on these devices. But with our recent changes you can now, when you need to, tap into the system namespace for more demanding behavior.
As you can see there is a lot of cool stuff in Smart Mobile Studio, and our codebase is maturing nicely. With out new organization we are able to expand both horizontally and vertically without turning the codebase into a gigantic mess (the VCL being a prime example of how not to implement a multi-platform framework).
Common behavior
One of the coolest things we have added has to be the new storage device classes. As you probably know the browser has a somewhat “limited” storage mechanism. You are stuck with name-value pairs in the cache, or a filesystem that is profoundly frustrating to work with. To remedy this we took the time to implement a virtual filesystem (in memory filesystem) that emits data to the cache; we also implemented a virtual storage device stack on top of it, one for each target (!).
In short, if a target has IO capability, we have implemented a storage “driver” for it. So instead of you having to write 4-5 different storage mechanisms – you can now write the storage code once, and it works everywhere.
This is a pretty cool system because it doesn’t limit us to local device storage. We can have device classes that talk to Google-Storage, One-Drive, Dropbox and so on. It also opens up for custom storage solutions should you already have this pre-made on your server.
Database support, a quick overview
Databases have always been available in Smart Mobile Studio. We have units for WebSQL, IndexDB and SQLite. In fact, we even compiled SQLite3 from native C code to asm.js, meaning that the whole database engine is now pure JavaScript and no-longer dependant on W3C standards.
Besides these we also have TW3Dataset which is a clean, Smart Pascal implementation of a single table dataset (somewhat inspired by Delphi’s TClientDataset). In our previous beta we upgraded TW3Dataset with a robust expression parser, meaning that you can now set filters just like Delphi does. And its all written in Smart Mobile Studio which means there are no dependencies.
And ofcourse, there is also direct connections to Embarcadero Datasnap servers, and Remobjects SDK servers. This is excellent if you have an already existing Delphi infrastructure.
A unified DB framework
If you were hoping for a universal DB framework in beta-2 of v3.0, sadly that will not be the case. The good news is that databases should make it into v3.2 at the latest.
Databases looks simple: table, rows and columns right? But since each database engine known to JavaScript is written different from the next, our model has to take height for these and be dynamic enough to deal with them.
The model we used with WebSQL is turning out to be the best way forward I feel, but its important to leave room for reflection and improvements.
So getting our DB framework established is a priority for us, and we have placed it on our timeline for (at the latest) v3.2. But im hoping to have it done by v3.1. So it’s a little ahead of us, but we need that time to properly evolve the framework.
Smart Desktop [a.k.a Amibian.js]
The feedback we have received on our Smart Desktop demos have been pretty overwhelming. It is also nice to know that our prototype is being used to deliver software to schools and educational centers. So our desktop is not going away!
But we are not rushing into this without some thought first. The desktop will become a project type like I have written about many times before. So you will be able to create both the desktop and client applications for it. The desktop is suitable for software that requires a windowing environment (a bit like Sencha or similar frameworks). It is also brilliant for kiosk displays and as a remote application hub.
Our new storage device system came largely from Amibian, and with these now a part of our RTL we can clean up the prototype considerably!
Smart assembler
It may sound like an oxymoron, but a lab project we created while testing our parser framework (system.text.parser unit) turned into an exercise in compiler / assembler making. We implemented a virtual machine that runs instructions represented by bytecodes (fairly straight ahead stuff). It supports the most common assembler methods, vaguely inspired by the Motorolla 68k processor with a good dose of ARM thrown in for good measure.
If you ponder why on earth this would be interesting, consider the following: most web platforms allow for scripting by third-party developers. And by opening up for that these, the websites themselves become prone to attacks and security breaches. There is no denying that any JS based framework is very fragile when potentially hundreds of unknown developers are hacking away at it.
But what if you could offer third parties to write plugins using more traditional languages? Perhaps a dialect of pascal, a subset of basic or perhaps C#? Wouldnt that be much better? A language and (more importantly) runtime that you have 100% control over.
While our assembler, disassembler and runtime is still in its infancy (and meant as a demo and excercise), it has future potential. We also made the instructions in such a way that JIT compiling large chunks of it is possible – and the output (or codegen) can be replaced by for example web assembly.
Right now it’s just a curiosity that people can play with. But when we have more time I will implement high-level parsers and codegens that emit code via this assembler. Suddenly we have a language that runs under node.js, in the browser or any modern JS runtime engine – and its all done using nothing but Smart Mobile Studio.
Well, stay tuned for more!
Alternative pointers in Smart Mobile Studio
Smart Mobile Studio already enjoy a rich and powerful set of memory handling classes and methods. If you have a quick look in the memory units (see below) you will find that Smart Mobile Studio really makes JavaScript sing and dance like no other.
As of writing in version 3.0 BETA the following units are dedicated to raw memory manipulation:
- System.Memory
- System.Memory.Allocation
- System.Memory.Buffer
- System.Memory.Views
Besides these, the unit System.Types.Convert represents the missing link. It contains the class TDataType which converts data between intrinsic (language level) data types and byte arrays.
Alternative pointers
While Smart has probably one of the best frameworks (if not THE best) for memory handling out there, including the standard library that ships with Node.js, the way it works is slightly different from Delphi’s and Freepascal’s approach.
Since JavaScript is reference based rather than pointer based, a marshaling offset mechanism is more efficient in terms of performance; So we modeled this aspect of Smart on how C# in particular organized its memory stuff.
But, is it possible to implement more Delphi like pointers? To some degree yes. The best would be to do this on compiler level, but even without such deep changes to the system you can actually implement a more Delphi-ish interface.
Here is an example of just such a system. It is small and efficient, but compared to the memory units in the RTL it’s much slower. This is also why we abandoned this way of handling memory in the first place. But perhaps someone will find it interesting, or it can help you port over code from Delphi to HTML5.
unit altpointers; interface uses W3C.TypedArray, System.Types, System.Types.Convert, System.Memory, system.memory.allocation, System.Memory.Buffer, System.Memory.Views; type Pointer = variant; TPointerData = record Offset: integer; Buffer: JArrayBuffer; View: JUint8Array; end; function IncPointer(Src: Pointer; AddValue: integer): Pointer; function DecPointer(Src: Pointer; DecValue: integer): Pointer; function EquPointer(src, dst : Pointer): boolean; // a := a + bytes operator + (Pointer, integer): Pointer uses IncPointer; // a := a - bytes operator - (Pointer, integer): Pointer uses DecPointer; // if a = b then operator = (Pointer, Pointer): boolean uses EquPointer; function Allocmem(const Size: integer): Pointer; function Addr(const Source: Pointer; const Offset: integer): Pointer; procedure FreeMem(const Source: Pointer); procedure MemSet(const Target: pointer; const Value: byte); overload; procedure MemSet(const Target: pointer; const Values: array of byte); overload; function MemGet(const Source: pointer): byte; overload; function MemGet(const Source: pointer; ReadLength: integer): TByteArray; overload; implementation function MemGet(const Source: pointer): byte; begin if (Source) then begin var SrcData: TPointerData; asm @SrcData = @Source; end; result := SrcData.View.items[SrcData.Offset]; end else raise Exception.Create('MemGet failed, invalid pointer error'); end; function MemGet(const Source: pointer; ReadLength: integer): TByteArray; begin if (Source) then begin var SrcData: TPointerData; asm @SrcData = @Source; end; var Offset := SrcData.Offset; while ReadLength > 0 do begin result.add( SrcData.View.items[Offset] ); inc(Offset); dec(ReadLength); if offset >= SrcData.View.byteLength then raise Exception.Create('MemGet failed, offset exceeds memory'); end; end else raise Exception.Create('MemGet failed, invalid pointer error'); end; procedure MemSet(const Target: pointer; const Value: byte); begin var DstData: TPointerData; asm @DstData = @Target; end; dstData.View.items[DstData.Offset] := value; end; procedure MemSet(const Target: pointer; const Values: array of byte); begin if Values.length > 0 then begin var DstData: TPointerData; asm @DstData = @Target; end; var offset := DstData.Offset; for var x := low(Values) to high(Values) do begin dstData.View.items[offset] := Values[x]; inc(offset); if offset >= DstData.View.byteLength then raise Exception.Create('MemSet failed, offset exceeds memory'); end; end; end; function EquPointer(src, dst : Pointer): boolean; begin if (src) then begin if (dst) then begin var SrcData: TPointerData; var DstData: TPointerData; asm @SrcData = @Src; end; asm @DstData = @dst; end; result := SrcData.buffer = dstData.buffer; end; end; end; function IncPointer(Src: Pointer; AddValue: integer): Pointer; begin if (Src) then begin // Check that there is an actual change. // If not, just return the same pointer if AddValue > 0 then begin // Map source data var SrcData: TPointerData; asm @SrcData = @Src; end; // Calculate new offset, using the current view // position as the present location. var NewOffset := srcData.Offset; inc(NewOffset, AddValue); // Make sure the new offset is within the range of the // memory buffer. Picky yes, but this is not native land if (NewOffset >=0) and (NewOffset 0 then begin // Map source data var SrcData: TPointerData; asm @SrcData = @Src; end; // Calculate new offset, using the current view // position as the present location. var NewOffset := srcData.Offset; dec(NewOffset, DecValue); // Make sure the new offset is within the range of the // memory buffer. Picky yes, but this is not native land if (NewOffset >=0) and (NewOffset 0 then begin var Data: TPointerData; Data.Offset := 0; Data.Buffer := JArrayBuffer.Create(Size); Data.View := JUint8Array.Create(Data.Buffer, 0, Size); asm @result = @data; end; end else raise Exception.Create('Allocmem failed, invalid size error'); end; function Addr(const Source: Pointer; const Offset: integer): Pointer; begin if (Source) then begin if offset > 0 then begin // Map source data var SrcData: TPointerData; asm @SrcData = @Source; end; // Check that offset is valid if (Offset >=0) and (offset < srcData.buffer.byteLength) then begin // Setup new Pointer data var Data: TPointerData; Data.Buffer := SrcData.Buffer; Data.View := SrcData.View; Data.Offset := Offset; asm @result = @data; end; end else raise Exception.Create('Addr failed, offset exceeds memory'); end else raise Exception.Create('Addr failed, invalid offset error'); end else raise Exception.Create('Addr failed, invalid pointer error'); end; procedure FreeMem(const Source: Pointer); begin if (source) then begin // Map source data var SrcData: TPointerData; asm @SrcData = @Source; end; // Flush reference and let the GC take care of it SrcData.Buffer := nil; SrcData.View := nil; SrcData.Offset := 0; asm srcData = {} end; end else raise Exception.Create('FreeMem failed, invalid pointer error'); end; end.
Using the pointers
As you can probably see from the code there is no such thing as PByte, PWord or PLongword here. We use a clean uint8 typed array that we link to a memory buffer, so “pointer” here is fully byte based despite it’s untyped origins. In reality it just holds a TPointerData structure, but since this is done via asm sections, the compiler cant see it and treats it as a variant.
The operators add support for code like:
var buffer := allocmem(1024); memset(buffer, $ff); buffer := buffer + 1; memset(buffer, $FA)
But using the overloaded memset procedure is a bit more efficient:
var buffer := allocmem(1024); var bytes := TDataType.StringToBytes('this is awesome!'); memset(buffer, bytes); buffer := buffer + bytes.length; // write more data here
While fun to play with and perhaps useful in porting over older code, I highly recommend that you familiarize yourself with classes like TBinaryData that represents a fully managed buffer with a rich number of methods to use.
And ofcourse let us not forget TMemoryStream combined with TStreamWriter and TStreamReader. These will no doubt feel more at home both under HTML5 and Node.js
Note: WordPress formatting of pascal code is not the best. Click here to view the code as PDF.
Smart Pascal assembler, it’s a reality
After all these years of activity I guess there is no secret that I am a bit over-active at times. I am usually the most happy when I work on 2-3 things at the same time. I also do plenty of research to test theories and explore various technologies. So it’s never a dull moment – and this project has been no exception.
Bytecode based compilation
For that past 7 years I have worked close to compiler tech of various types and complexity on a daily basis. Script engines like DWScript, PAXScript, PascalScript, C# script, JavaScript (the list continues) – all of these have been used in projects either inhouse or for customers; and each serve a particular purpose.
Now while they are all fantastic engines and deliver fantastic results – I have had this “itch” to create something new. Something that approach the problem of interpreting, compiling and running code from a more low-level angle. One that is more standardized and not just a result of the inventors whim or particular style. Which in my view results in a system that wont need years of updates and maintenance. I am a strong believer in simplicity, meaning that most of the time – a simple ad-hoc solution is the best.
It was this belief that gave birth to Smart Mobile Studio to begin with. Instead of spending a year writing a classical parser, tokenizer, AST and code emitter – we forked DWScript and used it to perform the tokenizing for us. We were also lucky to catch the interest of Eric (the maintainer) and the rest is history. Smart Mobile Studio was born and made with off the shelves parts; not boring. grey studies by men in lab coats.
The bytecode project started around the summer of 2017. I had thought about it for a while but this is when I finally took the time to sit down and pen my ideas for a portable virtual machine and bytecode based instruction set. A system that could be easily implemented in any language, from Basic to C/C++, without demanding the almost ridicules system specs and know-how of Java or the Microsoft CLR.
I labeled the system LDef, short for “language definition format”; I have written a couple of articles on the subject here on my blog, but I did not yet have enough finished to demo my ideas.
Time is always a commodity, and like everyone else the majority of my time is invested in my day job, working on Smart Mobile Studio. The rest is divided between my family, social obligations, working out and hobbies. Hence progress has been slow and sporadic.
But I finally have a working prototype so the LDEF parser, assembler, disassembler and runtime is no longer a theory but a functional virtual machine.
Power in simplicity
Without much fanfare I have finally reached the stage where I can demonstrate my ideas. It took a long time to get to this point, because before you can even think of designing a language or carve out a bytecode-format, you have to solve quite a few fundamental concepts. These must be in place before you even entertain the idea of starting on the virtual machine – or the project will simply end up as useless spaghetti that nobody understands or wants to work with.
- Text parsing techniques must be researched properly
- Virtual machine design must be worked out
- A well designed instruction-set must be architected
- Platform criteria must be met
Text parsing sounds easy. Its one of those topics where people reply”oh yeah, that’s easy” on auto pilot. But when you really dig into this subject you realize it’s anything but easy. At least if you want a parser that is fast, trustworthy – and more importantly: that can be ported to other dialects and languages with relatively ease (Delphi, FreePascal, C#, C/C++ are obvious targets). The ideas has to mature quite frankly.
One of my most central criteria when writing this system has been: no pointers in the core system. How people choose to inplement their version of LDEF for other languages is up to them (Delphi and FPC included), but the original prototype should be as clean and down to earth as possible.
Besides, languages like C# are not too keen on pointers anyways. You can use them but you have to mark your assemblies as “unsafe”. And why bother when var and const parameters offers you a safe and portable alternative? Smart Mobile Studio (or Smart Pascal, the dialect we use) doesn’t use pointers either; we compile to JavaScript after all where references is the name of the game. So avoiding pointers is more than central; it’s fundamental.
We want the system to be easy to port to any language, even Basic for that matter. And once the VM is ported, LDEF compiled libraries and assemblies can be loaded and used straight away.
The virtual CPU and it’s aggregates
The virtual machine architecture is the hard part. That’s where the true challenge resides. All the other stuff, be it source parsing, expressions management, building a model (AST), data types, generating jump tables, emitting bytecodes; All those tasks are trivial compared to the CPU and it’s aggregates.
The design and architecture of the cpu (or “runtime” or “virtual machine” since it consists of many parts) affects everything. It especially shapes the cpu instructions (what they do and how). But like mentioned the CPU is just one of many parts that makes up the virtual machine. What about variable handling? How should variables be allocated, addressed and dealt with? The way the VM deals with this will directly reflect how the byte code operates and how much code you need to initialize, populate and dispose of a variable.
Then you have more interesting questions like: how should the VM distinguish between global and local variable identities? We want the assembly code to be uniform like real machine code, we don’t want “special” instructions for global variables, and a whole different set of instructions for local variables. LDEF allows you to pass registers, variables, constants and a special register (DC) for data control as you wish. You are not bound to using registers only for math for instance.
I opted for an old trick from the Commodore days, namely “bit shift marking”. Local variables have the first bit in their ID set. While Global variables have the first bit zeroed. This allows us to distinguish between global and local variables extremely fast.
Here is a simple example that better demonstrates the technique. The id parameter is variable id read directly from the bytecode:
function TExample.GetVarId(const Id: integer; var IsGlobal: boolean): integer; inline; begin IsGlobal := ((byte((Id shl 24) shr 24) shr 1) and 1) = 0; result := Id shr 1; end;
This is just one of a hundred details you need to mentally work out before you even attempt the big one: namely how to deal with OOP and inheritance.
So far we have only talked about low-level bytecodes (ILASM as it’s called under the .net regime). In both Java and dot net, object orientation is intrinsic to the VM. The runtime engine “knows” about objects, it knows about classes and methods and expect the bytecode files to be neatly organized class structures.
LDEF “might” go that way; but honestly I find it more tempting to implement OOP in ASM itself. So instead of the runtime having intrinsic knowledge of OOP, a high level compiler will have to emit a scheme for OOP instead. I still need to think and research what is best regarding this topic,
Pictures or it didn’t happen
The prototype is now 97% complete. And it will be uploaded so that people can play around with it. The whole system is implemented in Smart Pascal first (a Delphi and FreePascal version will follow) which means the whole system runs in your browser.
Like you would expect from any ordinary x86 assembler program (MASM, NASM, Gnu ASM, IAR [ARM] with others) the system consists of 4 parts:
- Parser
- Assembler
- Disassembler
- Runtime
So you can write source code directly in the browser, compile / assemble it – and then execute it on the spot. Then you can disassemble it and look at the results in-depth.
The virtual cpu
The virtual CPU sports a fairly common set of instructions. Unlike Java and .net the cpu has 16 data-aware registers (meaning the registers adopt the type of the value you assign to them, a bit like “variant” in Delphi and C++ builder). Variables allocated using the alloc() instruction can be used just like a register, all the instructions support both registers and variables as params – as well as defined constants, inline constants and strings.
- R[0] .. R[16] ~ Data aware work registers
- V[x] ~ Allocated variable
- DC ~ Data control register
The following instructions are presently supported:
- alloc [id, datatype]
Allocate temporary variable - vfree [id]
Release previously allocated variable - load [target, source]
Move data from source to target - push [source]
Push data from a register, variable onto the stack - pop [target]
Pop a value from the stack into a register or variable - add [target, source]
Add value of source to target - sub [target, source]
Subtract source from target - mul [target, factor]
Multiply target by factor - div [target, facor]
Divide target by factor - mod [target, factor]
Modulate target by factor - lsl [target, factor]
Logical shift left, shift bits to the left by factor - lsr [target, factor]
Logical shift right, shift bits to the right by factor - btst [target, bit]
Test bit in target - bset [target, bit]
Set bit in target - bclr [target, bit]
Clear bit in target - and [target, source]
And target with source - or [target, source]
OR target with source - not [target]
NOT value in target - xor [target]
XOR value in target - cmp [target, source]
Compare value in target with source - noop
No operation, used mostly for byte alignment - jsr [label]
Jump sub-routine - bne [label]
Branch not equal, conditional jump based on a compare - beq [label]
Branch equal, conditional jump based on a compare - rts
Return from a JSR call - sys [id]
Call a standard library function
The virtual cpu can support instructions with any number of parameters, but the most common is either one or two.
I will document more as the prototype becomes available.
TextCraft 1.2 for Smart Pascal
TextCraft is a fast, generic object-pascal text parsing framework. It provides you with the classes you need to write fast text parsers that builds effective data models.
The Textcraft framework was recently moved up to version 1.2 and has been ported from Delphi to both Freepascal and Smart Pascal (the dialect used by Smart Mobile Studio). This is probably the only parsing framework that spans 3 compilers.
Smart Pascal coders can download the framework unit here. This can be placed in their $Install/Library folder (where $install is where Smart’s library and rtl folder is installed): BitBucket TextCraft Repository
Buffer, parser, model
Textcraft divides the job of parsing into 4 separate objects; each of them representing a concept familiar to people writing compilers; these are: buffer, parser, model and context. If you are parsing a programming language the “model” would be what people call the AST (short for “Abstract Symbol Tree”). This AST is later feed to the code generator, turning it into an executable program (Smart Pascal compiles to JavaScript so there really is no limit to the transformation, just level of complexity).
Note: Textcraft is not a compiler for any particular language, it is a generic text parsing framework that is language-agnostic. Meaning that it makes it easy for you to make parsers with it. We recently used it to parse command-line parameters for Freepascal, so it doesn’t have to be about languages.
The buffer
The buffer has one of the most demanding jobs in the framework. In other frameworks the buffer is often just a memory allocation with a simple read method; but in TextCraft the model is responsible for a lot more. It has to expose functions that makes text recognition simple and effective; it has to keep track of column and row position as you move through the buffer content – and much, much more. So in TextCraft the buffer is where text methodology is implemented in full.
The parser
Like mentioned the parser is responsible for using the buffer’s methods to recognize and make sense of a text. As it makes its way through the buffer content, it creates model-objects that represents each element. Typical for a language would be structures (records), classes, enums, properties and so on. Each of these will be registered in the AST data model.
The Model
The model is a construct. It is made up of as many mode-object instances as you need to express the text in symbolic form. It doesn’t matter if you are parsing a text document or source code, you would still have to define a model for it.
The model obviously reflect your needs. If you just need a superficial overview of the data then you create a simple model. If you need more elaborate information then you create that.
Note: When parsing a text document, a traditional organization would be to divide the model into: chapter, section, paragraph, line and individual words.
The Context
The context object is what links the parser to our model and buffer objects. By default the parser doesn’t know anything about the buffer or model. This helps us abstract away things that would otherwise turn our code into a haystack of references.
The way the context is used can be described like this:
When parsing complex data you often divide the job into multiple classes. Each class deals with one particular topic. For example: if parsing Delphi source code, you would write a class that parses records, a parser that handles classes, another that handles field declarations (and so on).
As a parser recognize mentioned objects, like say a record, it will create a record model object to hold the information. It will then add that to the context by pushing it onto its reference stack.
The first thing a parser does is to grab the model object from the reference to stack. This way the child parsers will always know where to store their model information. It doesn’t matter how deep or recursive something gets, the stack approach and passing the context object to the child parsers – will always make sure each parser “knows” where to store information.
Why is this important?
This is important because it’s cost-effective in computing terms. The TextCraft framework allows you to create parsers that can chew through complex data without turning your project into spaghetti.
So no matter if you are parsing phone-numbers, zip codes or complex C++ source code, TextCraft will make help you get the job done; in a way that is easy to understand and mentain.
Smart Mobile Studio: more cmd tools
Being able to compile and work with projects from the command-line has been possible with Smart Mobile Studio almost since the beginning. But as projects grows, so does the need for more automation.
Toolbox
The IDE contains a few interesting features, like the “Data to picture” function. This takes a datafile (or any file) and place the raw bytes into a png picture as pixels. This is a great way of loading data that the browser would otherwise block or ignore.
People have asked if we could perhaps turn these into command-line tools as well. And I have finally gotten around to doing just that. So our toolbox now contains 3 more command-line tools (not just the smsc compiler)
- Superglue
- DataToImage
Superglue
When you work with large JavaScript libraries they often consists of multiple files. This is great for JS developers and no different from how we use multiple unit-files to organize a project.
But it can be problematic when you deploy applications, because if the dependencies are heavy then your application will load slower. A typical example is ACE, the code editor we recently added to Smart. Its a fantastic editor, but it consists of a monstrous amount of files.
Superglue can import files based on a filter (like *.js) or a semi-colon delimited list. It will then merge these files together into a single file.
For example, let’s say you have 35 javascript files that makes up a library. And lets say you have downloaded and unpacked this to “C:\Temp” on your harddisk. To link all the JS files into a single file, you would type:
superglue -mode:filter -root:"C:\temp" -filter:"*.js" -sort -out:"C:\Smart\Libraries\MyLibrary\MyLibrary.js"
The above will enumerate all the files in “C:\Temp” and only keep those with a .JS file extension. It will sort the files since the -sort switch is set, and finally link all the files into a new, single file called MyLibrary.js (in another location).
So instead of shipping 35 files, which means 3d http loads, we ship one file and load the data in ourselves when the application starts.
DataToImage
As the name implies this is the same function that you find in the IDE. It takes a raw data file (actually, any file) and injects the bytes as pixels in a new PNG file. Code for extracting the data again already exist in the RTL – but I will brush up again on this when we add these tools to our toolbox.
Using this is simplicity itself:
datatoimage -input:"mysqldb.sq3" -output:"c:\smart\projects\mymobileapp\res\defaultdata.png"
The above takes a default sqlite database and stores it inside a picture. In the application we load the picture in, extract the data, and then use that as our default data — which is later stores in the browser cache. This saves us having to execute a ton of sql-statements to establish a DB from scratch in memory.
Better parsing
These tools are very simple. They dont take long to make, but they do need to be reliable. And they do need to be in place when you need them.
We actually ported over TextCraft, a parser we use both in Smart Mobile Studio and Delphi, so it would compile under Freepascal. There was a huge bug in the way Lazarus deals with parameters, so we ended up writing a fresh new command-line parser.
Future tools
We have a lot on our plate so I doubt we will focus on our toolbox much after these. They simplify library making and data injection for projects, and you can use a shell script to implement “make-files” that most people do these days.
However, one tool that would be very handy is a “project to xmlhelp” or similar. A command-line program that will scan your Smart project and emit a full overview of your classes, methods and properties in traditional xml-help format.
But we will see when time allows — at least making libraries and merging in data will be easier from now on 🙂
Fixed Header in Smart Applications
Smart Mobile Studio gives you a lot of really cool visual controls to play with. One of them is a header control (also called a navigation panel by some) that traditionally show and hide it’s buttons (back and next) in response to form navigation.
One question that many people have asked is: how can I make a header that remains fixed and doesnt scroll with the forms? So no matter what form I navigate to, the header remains in place. Preferably easily accessed.
The Visual Application
Smart Visual Applications are more than just forms and buttons. The first thing that is created when you run a visual Smart Application, is naturally an instance of TApplication; this in turn creates a display control, and inside that again there is something called a “viewport”. Forms are always created inside the viewport.
If you are wondering why on earth we use two nested containers like this, that has to do with scrolling and keeping our controls isolated in one place. Forms are positioned horizontally inside the viewport. So whenever you are moving from Form1 to Form2, depending on the scroll-effect you have picked, the second form is lined up either before or after the current form. We then execute a CSS3 animation that smoothly scrolls the new form into view, or the previous form out of view – depending on how you look at it.
The display
The root display control, TW3Display, has only one job; and that is to house the view control. It also contains code to layout child controls vertically. Since there is typically only one control present – that means you don’t notice much of what TW3Display does.
The “trick” to a static header that remains un-affected by forms, is simply to create the header control with “Application.Display” as the parent. That is all you have to do. You could also create it on Application.Display.View, but then it would cause problems with scrolling. My point for mentioning that is to underline how the RTL has no special rules for it’s structure. All visual entities that make up your Smart Pascal application follow the same laws and are subject to the same rules as TW3Button or TW3Label might be.
Creating controls that don’t attach to a form
The vertical layout that TW3Display does automatically is very simple. It sorts the child elements based on their Y position and places them directly after each other. This means that all you have to do is create the header and then make sure you give it a negative Y position, and it will always remain fixed on top of the Viewport and it’s forms.
TW3Application has a virtual method called ApplicationStarting() that is perfect for what we want to achieve. As the name says this method fires when the application is starting, so this is perfect for creating controls that don’t attach to a form. It also has an accompanying ApplicationClosing() method where we can release the control.
So let’s start by creating our control. Each visual application has a “unit1” that is created automatically. This contains your application object. While TApplication is a bit anonymous under Delphi or Lazarus, under Smart it serves a more central role. It’s the place you expose global values that should be usable throughout the entire program.
unit Unit1; interface uses Pseudo.CreateForms, // auto-generated unit that creates forms during startup System.Types, SmartCL.System, SmartCL.Components, SmartCL.Forms, SmartCL.Application, SmartCL.Controls.Header, Form1; type TApplication = class(TW3CustomApplication) private FHeader: TW3HeaderControl; protected procedure ApplicationStarting; override; procedure ApplicationClosing; override; public property Header: TW3HeaderControl read FHeader; end; implementation procedure TApplication.ApplicationStarting; begin inherited; FHeader := TW3HeaderControl.Create(Display); FHeader.SetBounds(0, -10, 100, 46); end; procedure TApplication.ApplicationClosing; begin FHeader.free; inherited; end; end.
Let’s compile and see what we got so far!

As expected we now have a header outside the form region
Global access
SmartCL, which is the namespace (a collection of units organized under one name) where all visual, DOM based classes live, have a global function for getting the Application object. This is simply Application() and you have probably used it many times.
What is not so well-known is that Application() returns a stock TCustomApplication instance. In other words, if you inspect the instance you will find none of the properties you have defined in TApplication. This is because TApplication is unknown until the application is executed. So in order to access your actual application object, you need to typecast; like I do here:
procedure TForm1.InitializeObject; begin inherited; {$I 'Form1:impl'} var app := TApplication(Application); app.Header.Title.Caption := 'This is my header'; end;
Let’s have a look at the result (note: I added a label as well, just so you don’t think you missed something):
Now this approach works fine for many types of objects. I tend to isolate my database instance there, static header, global storage — all of it can be neatly exposed via TApplication. Fast, simple and efficient.
The final step
The initial state for the static header should be that both buttons are hidden by default. So when you start the application it just shows a title, nothing more.
When you click something that cause navigation to form2 (or some other second form), the back-button should become visible once form2 has scrolled into view.
When the user click the back-button, the opposite should happen. The back button should be disabled while you navigate back to form1, then completely hidden once you have arrived.
I don’t think I need to demonstrate this. Obviously, if you have forms that leads to more forms – then you probably want to add a “navigation stack” to the application object – an array that holds the previously visited forms.
Then whenever someone hits the “back button” you just pop the previous form off the stack, and navigate to it.
Well, hope it helps!
HTML5 Attributes, learn how to trigger conditional styling with Smart Mobile Studio
Im not sure if I have written about Attributes before; Probably, because they are so awesome to work with. But today I’m going to show you something that makes it even more awesome, bordering on unbelievable.
What are HTML attributes again?
Before we dig into the juicy stuff, let’s talk about attributes. For those that dont know much about HTML or CSS, here is a quick and dirty overview. A lot of people use Smart Mobile Studio because they dont know CSS or HTML beyond the basics (or even because they dont want to learn it, quite a few cant stand JavaScript and CSS). Well that is not a problem.
Note-1: While not a vital prerequisite, I do suggest you buy a good book on JavaScript, HTML and CSS. If you are serious about using web technology (like node.js on the server) your Smart skills will benefit greatly by knowing how things work “under the hood” so to speak. You will make better Smart Mobile Studio applications and you will understand the RTL at a deeper level than the average user.
OK, back to attributes. You know how HTML tags have parameters right? For example, a link to another webpage looks like this:
<a href="http://blablabla">This is a link</a>
Note-2: I dont have time to teach you HTML from scratch, so if you have no idea what the “A” tag is then please google it.
Focus here is not on the “a” part, but rather on the “href” parameter. That is actually not a parameter but a tag-attribute (which must not be confused with a tag-property btw).
Back in the day attributes used to be exclusive; Meaning that if you tried to set some attribute value the tag didnt support – nothing would happen. The browser would just ignore it and the information would be deleted.
Around HTML4 all of that changed. Suddenly we got the freedom to declare our own attributes, regardless of tag. The only catch is that the attribute name must be prefixed with “data-“. Which makes sense because the browser needs to tell the difference between valid attributes, junk and intrinsic (supported) attributes.
Storing information outside the pascal instance
When you create a visual control, the control internally creates a DOM element (or tag object, same thing) that it manages. Most visual controls in our RTL manages a DIV element because that is just a square block that can be easily molded and shaped into whatever you like.
But, when you create a Smart Pascal class you dont just get a DOM element in return. You get a Smart Pascal object instance. This is the same as Delphi and Lazarus: a class is a blueprint of an object. You dont create classes you create instances.
The same thing happens when you use Smart Pascal: the JSVM (JavaScript virtual machine) delivers a JavaScript object instance – and that is what your code operates on. When you create a visual class instance, that in turn will create a DOM element and manage that until you release the Smart Pascal instance.
Storing information in a class is easy. It’s one of the fundamental aspects of object oriented programming and there really isnt that much to say about that. But what if you need to store information in a control you dont own? Perhaps you have installed a package you bought, or that a friend shared with you – and you cant change the class (or perhaps dont want to change the class). What then?
This is where the attribute object comes to the rescue. Because now you can store information directly in the DOM element rather than altering the class itself (!)
That is so powerful I dont even know where to start, because you can write libraries that can do amazing things without fields or demanding the user to change their controls (and in some cases, avoid forcing the user to inherit from a particular custom-control).
A real-life example
Our special effect unit, SmartCL.Effects.pas, uses this technique to keep track of effect state. When you execute an effect on a control a busy-flag is written as an attribute to the managed DOM object. And when the effect is finished the busy-flag is reset.
If you execute 10 effects on a control, it’s this busy flag that stops all of them running at the same time (which would cause havoc). While this attribute is set any queued effects wait their turn.
This would be impossible to achieve without declaring a busy property, or doing some form of stacking behind the scene; both of them expensive codewise. But with attributes it’s a piece of cake.
And now for the juicy parts
Now that you know what attributes do and how awesome they are, what can possibly make them even more awesome? In short: “CSS attribute pseudo selectors” (phew, that is a mouthful isnt it!).
So what the heck is a pseudo selector? Again its a long story, so im just going to call it “states”. It allows you to define styles that should be activated when a particular state occurs. The most typical state is the :active state. When you press a button the DOM element is said to be active. This allows us to write CSS styles that are applied when you press the button (like changing the background, border or font-color).
But did you know you can also define styles that react to attribute changes?
Just stop and think about this for a moment:
- You can define your own attributes
- You can read, write and check for attributes
- Attributes are part of the DOM element, not the JS instance
- You can define CSS that apply when an element has an attribute
- You can define CSS that apply if an attribute has a particular value
If you are still wondering what the heck this is good for, imagine the following:
With this, you can do the following:
- Write an event-handler for TW3Application.OnOrientationChange (an event that fires when the user rotate the mobile device horizontally or vertically).
- Store the orientation as a attribute value
- Define CSS especially for the orientation attribute values
The browser will automatically notice the attribute change and apply the corresponding CSS. This is probably one of the coolest CSS features ever.
Other things that come to mind:
- You can write CSS that colors the rows in a grid or listbox based on the data-type the row contains. So an integer can have a different background from a float, boolean or string. And all of it can be automated with no code required on your part. You just need to write the CSS rule once and that’s it.
- You can use attributes it to trigger pre-defined animations. In fact, you could pre define 100 different animations, and based on the attribute-name you can trigger the correct one. Again all of it can be neatly implemented as CSS.
Let’s make a button that triggers a style
While simple, the following example should serve as a good example. It’s easy to build on and not to complex. Let’s start with the CSS:
button[data-funky="this rocks"] { background: none; background-color: #FF00FF; font-color: #FFFFFF; font-size: 22px; font-weight: bold; }
The CSS above should be easy to understand. First we define the name of the DOM element, which in my case is a button. Next we define the attribute, and like mentioned it has to be prefxed with “data-” (our attributes class does this automatically in the RTL, so you dont need to prefix it when you code). And finally we define the value the style should trigger on, “this rocks”.
Right, let’s write some code:
var MyButton := TW3Button.Create(self); MyButton.SetBounds(100,280, 100, 44); MyButton.Caption := 'Click me!'; MyButton.OnClick := procedure (Sender: TObject) begin var Text := MyButton.Attributes.Read('funky'); if Text <> 'this rocks' then MyButton.Attributes.Write('funky','this rocks') else MyButton.Attributes.Write('funky',''); end;
The code is very simple, we read the value of the attribute and then we do a toggle based on the content. So when you click the button it will just toggle the trigger value.
This is how the button looks before we click it:
And when we click the button the attribute is written to, and it’s automatically styled:
How cool is that! The things you can automate with this is almost endless. It is a huge boon for anyone writing mobile applications with Smart Mobile Studio and it makes what would otherwise be a difficult task ridiculously easy.
Cheers!
You must be logged in to post a comment.