Skip to content

FireMonkey 2 Under The Hood Changes: Properties

There is another change in FireMonkey 2 in RAD Studio XE3 which does not show up on the What’s New page, but which pays dividends in terms of performance, usability and extensibility: Refining component properties.

The FireMonkey team has performed a comprehensive audit of all the component properties to re-examine whether each property should be published or not, whether the property’s default value is appropriate and whether it is published at the appropriate level of the component hierarchy tree. The result of this audit was a lot of little changes throughout the FireMonkey framework.

When a component property is published (that is, is appears in a published section of a class declaration), then the property will appear in the form designer’s Object Inspector at design-time. It also means that the value of the property can also be stored in the form file (.fmx file).

In RAD Studio XE3, many properties have been unpublished because their values were not relevant to the component and were not used by the component. By unpublishing these properties, it means that forms load more quickly because the runtime does not have to spend time reading and setting these property values. It also means that the Object Inspector is not littered with irrelevant properties, so the components are easier to use at design time.

For properties which remain published, the team has made sure that the properties are generally not published in base classes. This means that developers and technology partners which make custom components can precisely determine the properties which should be published in their custom subclasses.

This refinement helps FireMonkey become a more mature, more usable framework for cross-platform development.

Tagged , ,

FireMonkey 2 Under The Hood Changes: PlatformServices

RAD Studio XE3 introduces the next evolution of the FireMonkey framework: FM2. The What’s New in FM2 page highlights a lot of the new features. I wanted to point out some under the hood changes that are also significant.

Platform

One of the key concepts at the base of a cross-platform framework is providing an abstraction of the runtime environment, the operating system and hardware. In the original release of FireMonkey in RAD Studio XE2, this abstraction was provided by an abstract class, TPlatform. Each supported platform (Windows, Mac OS X and iOS) had a concrete implementation of this abstract class and it was accessed via a global Platform variable.

When the runtime platforms have similar features and capabilities, this approach is reasonable. As platform features start to diverge, however, this approach makes it difficult for a developer to know which parts of the abstraction are implemented on the runtime environment. This divergence was evident in the number of no-op implementations in the various platform units.

PlatformServices

In FM2, this abstraction has been significantly rewritten. Instead of a single abstract class, FM2 now has a registry of platform services, TPlatformServices (found in FMX.Platform.pas):

  TPlatformServices = class
  private
    FServicesList: TDictionary<TGUID, IInterface>;
    FGlobalFlags: TDictionary<string, Boolean>;
    class var FCurrentPlatform: TPlatformServices;
    class function GetCurrent: TPlatformServices; static;
  public
    constructor Create;
    destructor Destroy; override;
    class procedure UnInitialize;
    procedure AddPlatformService(const AServiceGUID: TGUID; const AService: IInterface);
    procedure RemovePlatformService(const AServiceGUID: TGUID);
    function GetPlatformService(const AServiceGUID: TGUID): IInterface;
    function SupportsPlatformService(const AServiceGUID: TGUID): Boolean; overload;
    function SupportsPlatformService(const AServiceGUID: TGUID;
      out AService: IInterface): Boolean; overload;
    property GlobalFlags: TDictionary<string, Boolean> read FGlobalFlags;
    class property Current: TPlatformServices read GetCurrent;
  end;

This class allows services to be added and removed from the registry, with the methods AddPlatformService and RemovePlatformService, respectively. The functions SupportsPlatformService provide a way for developers to query the registry to determine whether or not a particular service is supported at runtime. These functions were written to be similar to the Delphi RTL Supports functions for working with Delphi interfaces.

Services

So what is a platform service? It is simply an interface which defines some functionality which may or may not be implemented on a particular runtime platform. For example, this is the definition of the IFMXApplicationServices interface which defines the basic operations expected of an Application object:

  IFMXApplicationService = interface(IInterface)
    ['{EFBE3310-D103-4E9E-A8E1-4E45AB46D0D8}']
    procedure Run;
    procedure Terminate;
    function HandleMessage: Boolean;
    procedure WaitMessage;
    function GetTitle: string;
  end;

The FireMonkey TApplication object uses this service to control the application. FireMonkey cannot do very much without this service, so an implementation is provided for every runtime environment.

There are a number of other services which are not as essential. An on-screen keyboard is a good example. Functions to support an on-screen keyboard are provided by the platform service interface IFMXVirtualKeyboardService:

  IFMXVirtualKeyboardService = interface(IInterface)
    ['{BB6F6668-C582-42E4-A766-863C1B9139D2}']
    function ShowVirtualKeyboard(AControl: TFmxObject): Boolean;
    function HideVirtualKeyboard: Boolean;
    function GetVirtualKeyBoardState: TVirtualKeyBoardState;
    property VirtualKeyBoardState: TVirtualKeyBoardState read GetVirtualKeyBoardState;
  end;

To support the touch-oriented features of Windows 8, FM2 implements this service on the Windows platform. The service is not implemented for Mac OS X, however. Before a developer tries to use an on-screen keyboard, it is important to verify whether the service is supported or not, using code like this:

if TPlatformServices.Current.SupportsPlatformService(IFMXVirtualKeyboardService) then

Platform Growth and Advanced Uses

Changing the platform abstraction to a registry provides a much more powerful and flexible mechanism which will allow FireMonkey to be implemented on more platforms (for example, those mentioned in the RAD Studio Mobile Roadmap).

This mechanism provides a lot of power to developers to tailor applications to specific needs as well. For example, if a developer needs to provide an on-screen keyboard for a Mac OS X-based kiosk application, the developer can implement the IFMXVirtualKeyboardService interface and register it to get the FireMonkey support for on-screen keyboards.

It is also possible to unregister a service that FireMonkey does implement and replace it with a new implementation of the service which is tailored to fit the needs of a specialized application environment.

Tagged , ,

RAD Studio XE Editor Enhancements

There are a couple other little editor enhancements in RAD Studio XE that I wanted to highlight:

Templates In Code Completion

Code Templates have appeared in the code completion list for several releases. However, the code completion list has just shown the name of the code template. Often, the template name is not descriptive enough to know what the code template will do. In RAD Studio XE, the description of the code template will now also appear in the completion list:

Code Template Completion

Code Template Completion

Code Templates are one of the most powerful features of the RAD Studio code editor. This little enhancement should help to make them even easier to use.

Brace Highlighting

Brace Highlighting

Brace Highlighting

Brace Highlighting is another great editor feature that has been in RAD Studio for several releases. Personally, I find it invaluable for writing and debugging complex expressions. But, it is not popular with everyone. In RAD Studio XE, there is now a checkbox in the Editor Options (Tools/Options/Editor Options) for "Highlight brace pairs". It is checked by default and unchecking it will disable the Brace Highlighting feature.

RAD Studio XE Code Editor Search Shortcuts

Now that RAD Studio XE has shipped, I have a chance to post about some of the features that I worked on. Most of my time has been spent working on some features for future versions that I cannot talk about yet. But I did make a few small improvements to the RAD Studio XE code editor that are worth highlighting. I’ll start with my favorite little feature: a couple of keyboard shortcuts for searching in the code editor. I find myself using these new shortcuts several times a day.

When I’m searching for something in the code editor, I often know that the instance I want to find is above my cursor position. In previous versions of RAD Studio, I would usually press Ctrl+Home to go to the top of the file, then begin searching, hitting F3 a bunch of times until I found what I was looking for. In RAD Studio 2010, I would sometimes use the mouse to click the up arrow on the search bar, but the muscle memory of pressing Ctrl+Home, Ctrl+F would usually kick in before I thought of grabbing the mouse.

In RAD Studio XE, there are now two new keyboard methods for initiating a search: Shift+Enter and Ctrl+Enter. To use them, first invoke search (Search/Find, or Ctrl+F, or the equivalent in your favorite keybinding) and type your search term. Then to start your search, you can press:

  • Enter to search downwards.
  • Shift+Enter to search upwards.
  • Ctrl+Enter to search from the beginning of the file.

These keystrokes work only for initiating the search. As in previous versions, to find the next instance of the search term, you use the repeat search keystroke (in the default keybinding, F3 to search again downwards or Shift+F3 to search again upwards). Note that these new shortcuts do not change the search direction or scope for future searches. They are one-time modifiers.

This isn’t a big feature, but it’s one that I find myself using all the time.

In my next post, I’ll point out a few other little editor changes in RAD Studio XE.

Code Navigation In The RAD Studio Code Editor

During the recent field test for RAD Studio 2010, I had a discussion with some field testers about the different mechanisms that the IDE provides for navigating through your source code. In particular, they were wondering why sometimes one method of code navigation fails, but other methods still work. I thought that this would be of interest to some of you as well, so I figured that I’d post about it here.

The IDE provides four common ways of navigating through your code within the code editor:

  1. Code Browsing (also known as Ctrl-Click or Go To Declaration)
  2. Toggling between interface and implementation sections
  3. Open File At Cursor
  4. Help Insight navigation links

The mechanism behind each is completely different and some are more tolerant of incomplete or broken code than others.

Code Browsing/Go To Declaration (Ctrl-Click)

Code Browsing is supported in both Delphi and C++Builder. It is invoked when you hold down the Ctrl key and move the mouse over a symbol. This underlines the symbol, like a web page link that you can click on. You can also right-click on a symbol and choose “Go to declaration” from the context menu. This method of navigation works by invoking the compiler in a special browsing mode that we call “kibitzing.”

The IDE asks the compiler to find the declaration of the symbol. The compiler goes off and partially compiles enough source code to be able to find the declaration. It reports back to the IDE with either the filename and line number of the declaration or with an indication it couldn’t find the declaration.

In this browsing mode, the compiler works a little differently than when it actually builds your project. When browsing, the compiler’s back end is turned off so that no binary code is produced. The compiler is also more relaxed about syntax errors. It has several error recovery mechanisms that allow it to keep parsing through some incomplete or incorrect code, too. Still, if the code is too incomplete or too incorrect, the compiler may not be able to recover and code browsing may fail.

For Delphi projects, the compiler’s browsing mode also differs from the regular compile operation in that it uses a different path for resolving units listed in the uses clauses. In browsing mode, the compiler does not use the program (.dpr) or package (.dpk) file. Instead, it just compiles the particular unit that you are working with and it tries to find the units in the uses clauses by looking on the project’s search path and the global browsing path. Before starting a browsing operation, the IDE adds the paths for all of the units listed in the project manager to the browsing path and passes this extended browsing path to the compiler. If you hand-edit the program or package source to include units that are not listed in the project manager, then the compiler may not be able to find them and this can make code browsing fail. If you hand-edit the program or project source, it is very important that your global browsing path include the directories for all of the source code that may be pulled into your build.

For C++Builder, the program or package source does not list the used units like Delphi does. When the C++ compiler is in browsing mode, it always tries to find the source along the project’s include path or the global browsing path.

Toggle Between Declaration and Definition (Ctrl-Shift Up/Down)

Toggling between the interface declaration and implementation definition of a method is supported only for Delphi projects. Pressing Ctrl-Shift-Up Arrow will show the method’s declaration and pressing Ctrl-Shift-Down Arrow will show the method’s implementation.

This method of code navigation does not invoke the compiler at all. It is an entirely IDE-based mechanism that uses the same per-unit parser that provides the editor’s code folding regions and the structure pane information. This parser is even more resilient to code errors because it looks only for structure elements and it completely skips procedure bodies. As long as the parser is able to locate the procedure header for both the declaration and implementation then this method of code navigation will work, even on code that would not yet compile.

Open File At Cursor (Ctrl-Enter)

“Open file at cursor” is another mechanism of navigation that is available in both Delphi and C++Builder. This method of code navigation takes a very simple approach:

The IDE simply looks at the token underneath the cursor. For Delphi, if the token does not have an extension, the IDE appends “.pas” to the token then looks along the project’s search path for a matching filename. For C++Builder, the IDE just takes the editor token and tries to find it as a filename along the include path.

For both personalities, if the IDE is unable to find a matching filename it will show the standard File Open dialog.

Help Insight Links

Help Insight is available only in Delphi projects. When your mouse hovers over a symbol in the code editor, a pop-up window will appear with additional information about the symbol, including a hotlink to the symbol’s declaration.

Information for Help Insight is produced by yet another IDE-based parser. This parser also provides the information for Error Insight and powers the refactoring and modeling features. It is a more complete parser than the structure parser, but it was designed to be very resilient when it encounters incomplete or incorrect code. For units within the project, this parser looks at all the source code. For used units that are not listed in the project manager, the parser invokes the compiler to find the exported symbols.

I hope this helps to explain the different navigation mechanisms that are available in the RAD Studio IDE and gives some insight into how they work.

CodeRage 4 Next Week

Would you like to see the new code editor Search Bar and Search Highlighting in action? Do you have questions about it, or about other new features of the RAD Studio 2010 code editor? Then make sure you register for next week’s free CodeRage 4 Virtual Developer’s Conference. I just finished recording my short segment that will be part of the "New Features in the RAD Studio IDE" session. This session debuts on Tuesday and is repeated on Friday. Following the pre-recorded portions of the session, I will be available for questions along with other members of the RAD Studio IDE team. The conference is free and it looks like there a lot of great sessions, but you need to register to attend. Click the image below for more information.

RAD Studio 2010 - Refactoring & Help Insight for Generics

Another enhanced feature in the RAD Studio 2010 and Delphi 2010 IDE is better support for Delphi generics. Both refactoring and Help Insight were updated to support generic types.

Refactoring

In Delphi 2010, it’s now possible to perform rename refactoring on generic type and method symbols:

Rename Generic

Rename Generic

Change Parameters refactoring lets you add or remove procedure or function parameters from a generic procedure type:

Change Parameters Refactoring

Change Parameters Refactoring

Extract Method refactoring will work in code that contains generics, too.

Help Insight

Help Insight now gives a bit more information for generic types, too. When you hover over a variable that is declared as an instance of a generic type, you’ll see the actual type details:

Help Insight for Generics

Help Insight for Generics

These are just a couple small changes that make it even easier to work with generic types in Delphi.

Tagged ,

Embarcadero RAD Studio 2010

We have been given the green light to talk about some things that we’ve been working on for Embarcadero RAD Studio 2010 (and Delphi 2010 and C++Builder 2010). I figured that was a good excuse to get started here since I do have a couple new code editor features that I’d like to show off.

Search Highlighting

The search function of the code editor is one of those workhorse features that gets used all the time. While it does its job well, sometimes it seems that it could be a bit smarter. For example, if my cursor is past the instance that I’m really looking for, I often end up invoking to search a couple times to find it. This is because the search only shows one match at a time and it only searches in one direction at a time.

One of the first features I worked on for RAD Studio 2010 was to make the code editor find all the matches all at once. So performing a code search now looks something like this:

Here the "primary" search match is highlighted, just as it always has been (in black here). But now all the other matches are shown as well (highlighted in orange). You can scroll up and down with the scrollbar or scroll wheel and if any other matches become visible, they’ll show up right away.

Each color scheme has an appropriate default color for the additional search matches and the color can be customized as well.

Search Bar

In RAD Studio 2010, we’ve replaced the modal search dialog with a search bar at the bottom of the code editor:

When search is invoked, this bar pops up. It is modeless, so it’s easy to switch back to the editor, for example to copy a search term from the editor. Forward and backward searching is as easy as clicking on the down or up arrows (there are keyboard shortcuts for each, too). The third arrow button restarts the search from the beginning of the file. As before, the search box maintains a history of searches. All the search options can be set by using the checkboxes on the search bar.

Since the search highlighting feature knows where all the matches are, the search bar also shows a count of how many matches exist within the entire file.

Between these two changes, I hope you find the code editor search to be even more useful than ever.

Tagged , ,

Bad Behavior has blocked 17 access attempts in the last 7 days.

Close