Welcome to the first chapter of this book! We are at the beginning of a journey to gain knowledge about a great application framework, that is, the FireMonkey (FMX) framework. These days, developers face a hard-to-solve problem—building effective cross-platform applications. From a project management point of view, one of the most wanted features is to achieve this goal through a single source code base, not, for example, having a different code base for each supported platform.
The introduction of the FireMonkey framework represented a crucial point, putting Embarcadero Delphi in a magic spot in the global software development scenario. Developers are enabled to design and build native applications for the most popular platforms, including both desktop (Microsoft Windows, Linux, and Apple OS X, now also known as macOS) and mobile (Google Android and Apple iOS), using a single toolset and language (thus reducing the effort needed).
This chapter will go through the following topics, to provide some background about what FMX is, why it was created, and its most evident strengths:
- Approaching FireMonkey
- Abstracting the visual part of your apps
- Looking beyond the UI
- Back to the metal
- Understanding the strengths and weaknesses of the FMX approach
After reading this chapter, you will be familiar with the general context in which this framework has been developed, including a general understanding of the underlying philosophy of the chosen approach.
Here is the source code used in this chapter: https://github.com/PacktPublishing/Delphi-GUI-Programming-with-FireMonkey/tree/master/Chapter%2001/HelloWorld.
Generally speaking, for the whole book, you need a computer with Delphi set up and a few additional libraries installed (such as Radiant Shapes (https://getitnow.embarcadero.com/?q=radiant+shapes) and CodeSite Logging (https://getitnow.embarcadero.com/?q=codesite)). Having other physical devices and setting up multiple platforms (iOS, Android, OS X/macOS, and Linux) other than Windows is a plus but not strictly needed to follow the flow of the book.
In this section, we will explore the general background we need to properly introduce the FMX framework. Delphi is a longevous environment and it existed way before the FMX framework. We need to delve a bit into the roots of the Delphi tool to understand FMX in a better way.
When I was still a teenager, Delphi was the best development environment to build Microsoft Windows applications. I had some Turbo Pascal background knowledge and someone told me to give Borland Delphi a try in order to easily get into visual application development. That was during the time of Windows 95 and the world, from an IT point of view, was much simpler than today. DOS and Windows had a very large share of personal computer coverage. The remaining part of the world was running Linux or Macintosh but with a limited share and only in very specific contexts. Even though the mainframe (such as IBM AS400) was still a thing, business companies were mostly running Windows.
Given that I had limited DOS programming knowledge, I spent a lot of time learning how to build a Windows GUI application and also experimented with other languages (such as Visual Basic, Java, and Visual C++) but Delphi has been my favorite right from the start.
The ability to easily build beautiful Windows applications through a designer is still a great plus and I really think this has been one of the key factors of Delphi's success. The following screenshot shows the Delphi 10.4.1 Sydney splash-screen:
Apart from the convenient GUI Rapid Application Development (RAD) approach, built into an effective IDE, Object Pascal was a great language showcasing full Object-Oriented Programming (OOP) support, great C compatibility (perfect for Windows API calls), and featuring a very fast compiler. Generated applications also had outstanding runtime performances.
Looking at Delphi as a whole product, what surfaces is a fantastic tool, capable of letting developers focus on their application code while building fast, good-looking, modern applications – a shiny gem to easily deliver proper and curated GUI applications for the Microsoft Windows platform. In other words, the product performed very well by being more abstracted than raw C/C++ programming and proving to be way more powerful than Visual Basic (just to cite two of the biggest Delphi competitors over time).
This has been possible thanks to a framework shipped with the product: the Visual Component Library (VCL). It acted as a sort of abstraction over the standard Windows controls, wrapping them in a more suitable and easy-to-use programming interface. A big difference with respect to other products has been that all this provided the ability to go back to being low-level and interact with the primitive control whenever needed.
Using the VCL was convenient and the library naturally evolved over two decades (at least!) of development by covering more and more Windows features and capabilities. Every Delphi developer felt at home while dealing with VCL components and most applications never needed to breach into low-level code. This meant higher productivity for the developer and I myself have seen several projects started with other technologies then being abandoned due to running over time for the project execution. Developer teams struggled to deliver functionalities in years while the same project revamped with Delphi came to a successful conclusion within months.
Today, the general scenario is much more complex than what it looked like in the late 1990s. We have seen the rise of mobile platforms and at the time I am writing this, a mobile Operating System (OS) (that is, Android) is now the most used OS worldwide. Also, the desktop platforms scene has seen some changes and now Apple’s Mac OS X (aka macOS) has much more widespread adoption than before (even if this is not equally true in every part of the world). Linux somewhat lost the race for desktop user adoption (I am not considering Android as a Linux family member, even though it is Linux kernel-based) but got a relevant position as a server-side platform (driving the web, one could say).
In the following graph, you can see OS distribution over time (period starting January 2009 to January 2020 – data source: https://gs.statcounter.com):
From the preceding graph, it is easy to spot the decline of Windows (the dominant platform from 2009 up to 2017) and the corresponding rise of Android (with it overtaking around 2018).
Generally speaking, today, multi-tier architectures have become the de facto standard for real projects that have to deal with a (possibly high) number of heterogeneous clients and need to provide users with proper interfaces in very different scenarios (desktop, mobile, web platforms across different device families). Due to this fact, it's more and more challenging to see applications as single projects, built for a specific platform (as it was for decades). The availability of an application across multiple platforms has become a very demanding feature (it has almost become an intrinsic standard requirement).
To build and maintain multiple (one per supported platform) development projects, just to deliver the same functionalities to all involved final users, is costly from several points of view. It is hard because developers will have to learn platform-specific behaviors, technologies, APIs, programming languages and deployment toolchains. This requires several different, demanding skills. It will likely mean more than a single development team will be required to accomplish the mission. This also quickly leads to maintainability issues over time, with a huge impact on the total cost and time-to-market of the product you are building. Even if building a specific application for each platform sounds too expensive, the other option (to build a single cross-platform application) has to address some not so evident issues.
First of all, nobody really wants to have a cross-platform application framework that only enables the developer to rely on the common shared part of all platforms. Obviously, this approach (the greatest common divisor) would fall short as platforms are diverging in terms of functionalities and even those capabilities available on all platforms usually have some interface/implementation details that make them hard (or expensive/inefficient) to abstract.
At the same time, nobody needs a framework that is a composition of specific functionalities gathered from all supported platforms as this would result in something actually enabling developers to build applications relying on all functionalities of all platforms but forcing them to write different code (in the same language, though) for each platform (that is, the general problem the framework has been built to solve).
The solution (as often happens) is something in between these two opposites. FireMonkey is in a nice spot, thanks to its mixed strategy. Being a sort of compromise, it goes without saying that this also translates into a list of related strengths and weaknesses.
In the following screenshot, you can see the Delphi IDE while designing a multi-platform application. The Android style is selected for use in the form designer, an iOS style preview is available through the Multi-Device Preview window (docked into the IDE on the right side) and an instance of the application is running on the Windows platform, just in front of the IDE itself—three styles visible at the same time, one per platform; three different binaries using the same (single) source code:
As you can see, the cross-platform capabilities of Delphi are highlighted in the preceding screenshot. You are building your application (using a single programming language: Delphi), addressing multiple platforms easily. You can design your app in the IDE, select one of the supported styles (each style being associated with a specific platform—Android, as shown in the previous screenshot) to preview the result in the form designer, seamlessly. At the same time, you can also have a look at Multi-Device Preview (part of the IDE set of functionalities named Fire UI). There, you'll get a realistic preview of how your application will look on other (multiple, eventually) platforms (iOS, which is also shown in the preceding screenshot).
Note that neither of the two mentioned platforms (Android and iOS) is the one that your IDE is running (Windows) and that your app will also be able to be executed, no code changes needed, on Windows (and Linux and OS X/macOS). Doesn't sound great enough? Then you can go even further and have your forms previewed, live, on a mobile device through another technology named Live Preview (still part of the Fire UI set, http://docwiki.embarcadero.com/RADStudio/en/FireUI_Live_Preview). This time, you'll be able to preview (without having to wait until the compilation time) your UI on actual physical devices, without effort, with the screen of the device acting as an extension of your IDE.
In this section, we discussed the current scenario of software development, describing how and why we are facing the need to deliver multi-platform applications. We also introduced the FMX framework approach, with respect to the difficulties of the implementation of the same application using different tools to address different platforms.
In the next section, we are going to focus on the strategy FMX takes in order to provide different UI visuals to match the current platform of the running application.
Abstracting the visual part of your apps
The first version of the FMX framework was released in 2011 and already had one of its fundamental features, that is, the rendering of the UI was done completely from scratch, using the GPU. At the time, the GPU already supported technologies such as shaders (https://en.wikipedia.org/wiki/Shader), opening up a way to implement high-quality vector graphics, also considering the CPU growth in terms of computational power.
It became possible to build complex UIs, decorated with stunning effects and transitions, reaching the same appealing visuals typical of technologies such as Flash (the leading technology in modern and good-looking UIs, at the time). Given that WinAPI (thus, the VCL) and the new (at that time) .NET alternatives - Windows Presentation Foundation (WPF) were not covering the capabilities, the development team of FMX saw a great opportunity to build a new framework and, thankfully, they decided to take the chance.
This was the beginning of the framework having the opportunity to control every aspect of the UI implementation, opening the possibility to strongly abstract the UI from platform-specific controls and capabilities, but the number of controls available was limited and the first version of FMX was not really able to catch up with the same level of functionalities offered by the VCL on Windows.
The major new feature added with FMX 2 was bitmap styles: building a rich vector-based UI had a huge impact on performance and, at the same time, it was hard to implement some of the required components and peculiarities of the UIs. Adding the bitmap style capability moved FMX into the position to build effective, good-looking (pixel-perfect was the motto at the time), and performant applications, still keeping strong abstraction (through the style concept).
Even though it may seem a step backward (from pure vectors to bitmap styles), one should consider that most computer graphic evolution over the decades has gone in a direction where bitmaps were a central part of the game, thus most operating systems and drawing technologies are very familiar with bitmap (raster images) handling and have been optimized for that.
In the next couple of sections, we'll explain why the FMX framework is to be considered an application framework rather than a merely visual framework. It is important for you to properly understand that the general approach toward cross-platform application development has a lot to do with the visuals (we are focusing on visual applications), but there's much more to consider.
Looking beyond the UI
Even though many current prototyping tools tend to see an application as a bunch of views, we all know that a real application is not made only of a set of mere visual assets.
While building a cross-platform application, you obviously wish your visual application framework (FMX in the case) to deal with visual aspects but at the same time, to provide actual functionalities. This is because you will end up needing some level of interaction with the platform your application is running on.
Modern applications have to provide advanced functionalities, including some that are really basic (not always trivial, though), such as (multi-)touch support, and interaction with the system clipboard or with the filesystem. There are some possibly more specific topics, such as sensor integration (camera and positioning, for example), or other device-/platform-specifics such as notification systems, voice recognition, text-to-speech, and other advanced capabilities.
What I am trying to say is that FMX (and the Delphi RTL parts added by Embarcadero in recent years, available both for FMX and VCL) is much more than a visual framework, that is, it provides powerful abstractions that a developer can use to implement functionalities in a real cross-platform way.
This is true and evident in many areas we will cover throughout this book. Starting from behavioral services, with the aim of abstracting some device-/platform-specific behaviors (such as tab positioning in tab control or the default presentation mode of some components such as TMultiView, commonly used to implement mobile app menus). We could also abstract audio/video services, where a single, shared interface lets you access device cameras, microphones, or other common (but specific) aspects related to the multimedia area.
Just as a simple example, iOS and Android use different file formats for audio and video, thus to have a single TMediaPlayer component leveraging this difference is very convenient for the developer, that is, just ask the component to play or record audio/video with the same code.
Accessing the storage of the device (the camera roll for iOS or the Gallery/Photos apps for Android) is another great example. There are many functionalities (the device contact list to name another one), and it is hard to provide an exhaustive list.
You may think this list would represent the playground for the app developer but this is only partially true, that is, the VCL has a great level of abstraction over most Windows controls and APIs. Though, you always had a chance to go back to the metal, breaking this generally convenient abstraction and tweaking your code, adding low-level Windows API calls (without confining your possibilities to what the framework offers) and this is true also in the FMX framework, as we will see in the next section.
Back to the metal
Each strong abstraction can easily become a golden cage for its user. This also applies to software development and frameworks where you may obviously like the fact the framework is hiding the complexity underneath and providing a simple, clean, and comfortable place where the developer can live with fewer worries with respect to a more raw approach where everything is the developer's responsibility (embracing the subsequent complexity as much as they can afford).
At the same time, this kind of safe playground (always) has some boundaries and the developer can sometimes reach one of these boundaries and will go (or need to go) further.
Delphi always shined in this, letting you stay warm and safe with your VCL components wrapping Windows controls but, at the same time, letting you directly call whatever external function was available, including, of course, all WinAPI functions. When coming to FMX, as I said, I considered it to be more than a visual framework but rather an application framework; this is still true because, even if you can’t handle FMX controls using APIs designed for native controls, you can still have your FMX (and RTL) Delphi code with platform-specific calls to the underlying APIs of the currently running OS.
This means you (from your Delphi code) can call any iOS library functions (as you would do in Objective-C or Swift). The same applies to Android where you can wrap (there is the Java2OP tool available for Embarcadero’s registered users) the Java code you want to reach into Delphi classes and functions and have it available for your application developer. Even though this may seem like a kind of last refuge for the developer, it also represents a guarantee that your framework (FMX) is not closed and you are actually able to get back to the metal as much as you like or need.
For example, it is not unusual, when writing Android apps on custom devices (that is, those including industrial-level optical or NFC/RFID readers) to have the manufacturer of the device provide it with a standard Android OS image with the addition of some external JAR files with the libraries needed to properly interface with some device-specific features. Also, it guarantees that if Embarcadero is not providing you this or that API wrapper, you may proceed and generate it (manually or with a tool such as Java2OP) without having to wait for official support for that functionality.
In the next section, we'll try to consider the good and the bad coming from the peculiarities of the FMX approach.
Understanding the strengths and weaknesses
So far, we have simply introduced the FMX framework, exploring both the surroundings in which an FMX application should live and the context the technology was created in.
In this section, we will discuss how the FMX framework performs in the context that it is intended to be used in (the development of cross-platform applications). We'll consider some topics representing the strengths and weaknesses of the FMX approach. This should help you understand where in the big picture of multi-platform development tools we are.
At first, consideration is given to the available continuity from VCL to FMX. At first sight, you can appreciate the fact that an experienced Delphi (VCL) developer has been provided with a chance to reuse part of their knowledge and experience while moving from a single (very specifically, Windows) platform development environment to a multi-platform (and/or cross-platform). The existence of FMX has enabled all those Delphi developers to not have to start from scratch (possibly doing this multiple times, one for each platform to address) while making their first steps into new scenarios (such as mobile platforms).
This is far better than having completely different toolsets, especially if you are building a project supporting multiple platforms and also if you are a developer of several projects targeting different platforms. Today, we are starting to diffusely see software (applications) as the backbone of industries and, more generally, today, everything seems to have a somewhat software core to it, with the IT industry gaining more and more consideration and respect. At the same time, this means a huge increase in the demand for software with sustainable costs in terms of money and delivery time, with more and more demanding quality factors.
As we already addressed earlier in this chapter, enabling existing developers (with their valuable experience baggage) to cover new platforms instead of having to raise new (inexperienced) developers, from scratch, on each new platform is obviously a game-changer opportunity that we should try to catch as much as possible. Just to name a clear example where this whole system shines, think about the data access components (and their knowledge) you can naturally use within applications of both the FMX and VCL frameworks. Every business application I’ve seen in 15 years (and counting) of consulting in the IT world had some data-centric part somewhere (often, the most relevant one). We will give an overview of this topic in Chapter 4, Discovering Lists and Advanced Components, covering FireDAC utilization within FMX applications.
Another strength factor FMX has is the possibility to add support for new platforms on the go. Just before the Apple iPhone launch (2007), nobody would have ever guessed that Nokia’s Symbian OS would become a dead platform so quickly. The story of Microsoft mobile operating systems has also been subject to lots of change and with some bumps (think about Nokia acquisitions and Nokia X device families that are commercialized by Microsoft but with a custom Android OS on board).
Generally speaking, the mobile world has seen some new entries and some unexpected passings for a while. Today, we can reasonably think of the mobile world as having a substantial split between Android and iOS but, at the same time, we should always consider the fact that a new platform may arise tomorrow. Even though it is not really a new platform, the recent addition of Linux as a target platform for FMX GUI applications has been seen as a new conquest by the whole Delphi community. This addition has been possible thanks to the new implementation provided by a third-party vendor named KSDev (embodied by the original FMX authors, Eugene Kryukov and Alexey Sharagin) and the effort by Embarcadero to deliver a new compiler for the Linux (Intel) platform.
Together with the LLVM compiler technology, the inner architecture of the FireMonkey framework obviously is responsible for this accomplishment, which puts Delphi in a position to build effective UI applications on up to five different platforms, namely, Microsoft Windows (32-bit and 64-bit), Apple OS X, Apple iOS (and its simulator), Google Android, and Linux (Ubuntu and RedHat are officially supported by the compiler). From a strategic point of view, knowing the set of tools your IDE uses to actually build your applications is extensible (from the compiler to the UIs, including RTL and main DAC libraries) has a lot of value, especially if you are building large applications or you have an estimated lifespan for your projects of more than a couple of years.
Obviously, there are also some drawbacks. There always are, especially in such a high-demanding and dynamic environment made of moving targets (such as mobile platforms). The first obstacle is caused by the high-level abstraction I have described in this chapter. That is, Embarcadero’s whole cross-platform solution is made of abstractions of services and functionalities where the construction of the UI is one of the most relevant in terms of the user experience (more and more of a central success factor for every piece of software out there, from the user's (and customer's) point of view). The key strengths of FMX (such as styles and the ability to perfectly mimic a native application's visual and interactive pattern fundamentals) should strongly mitigate the distance from the top of the abstraction and the bare metal on the ground, but this still remains a challenge.
The speed in innovation, especially in mobile platforms, we are perceiving today can be hard to handle and integrate into a highly abstracted framework. Embarcadero has some opportunities to solve (or at least mitigate) these problems and the first example in this direction has been the introduction of the ControlStyle property, with the platform option to let FMX use a corresponding native control where the developer decides it is worth doing so. This means that if the underlying OS has some advanced features (think about a device-wide orthographic corrector or an advanced dictation system) built into native controls, even cross-platform applications built in FMX can rely on them and not lack behind other apps.
In the same area, relatively young mobile platforms are continuously evolving, trying to improve their performance and so the FMX framework (and Embarcadero’s ecosystem of technologies) will have to improve over time to catch up with native applications (whatever native applications might mean—you should read native here as in non-cross-platform applications).
There is a strange point in my mind and it isn’t so easy to state whether it is a strength or a weakness, that is, Embarcadero is a relatively small player compared with Apple, Google, and Microsoft. This means they obviously have to strive to follow the major decisions of those big players (who all make money from things other than developer tools) and at the same time, it means they have a chance to be more agile and less extremist than them. They have the opportunity to provide a common path to all platforms (a very ambitious goal).
In this chapter, we introduced the FMX framework, including the historical reasons behind its creation and the context of where it all began. The philosophy of the framework (and its inner evolution) should act as support for the rest of the book and should provide you with some basic understanding for the rest of the content of the book.
If you are an experienced Delphi developer, this chapter should have provided you with a non-technical bridge from classic Delphi to the newer versions, now including this second application framework, other than the original VCL. At the same time, if you are a developer addressing Delphi for the first time, a little background information should help you go through the rest of the content of this book.
In the next chapter, we will explore differences and similarities with respect to the VCL. This will serve experienced developers to learn how many of their skills they can reuse and what they need to keep in mind for their new projects. If you are new to Delphi and will start with FMX, you will nonetheless find some useful basic information about how FMX works, so turn the page and go ahead!