A bunch of Spring4D dependency injection container related questions

Since G+ is down, a lot of interesting questions have vanished. Luckily I saved some by [WayBack] Jacek Laskowski – Google+ related to Spring4D and dependency injection: [WayBack] Spring4D IoC and specific singleton… – Jacek Laskowski – Google+ First my Google Groups archival reminder: Rename from https://groups.google.com/forum/?hl=en#!topic/spring4d/zZZXOmMzF4I To https://groups.google.com/d/topic/spring4d/zZZXOmMzF4I Save that URL with Archive.is Q: [WayBack] Spring4D – How to get the same instance of Logger for a class group?… – Jacek Laskowski – Google+ Everything works on interfaces, but I skip interfaces for simplicity. I have a base class:  TBaseClass = class   fLogger : TLogger;  end; Two usable classes are inherited from it:  TClassA = class(TBaseClass)   fWorkClass1 : TWorkClassA;     fWorkClass2 : TWorkClassB;  end; TClassB = class(TBaseClass)   fWorkClass3 : TWorkClassC;   fWorkClass4 : TWorkClassD;  end; …which have working classes:  TWorkClassA = class   fLogger : TLogger;  end; TWorkClassB = class   fLogger : Tlogger;  end; TWorkClassC = class   fLogger : TLogger;  end; TWorkClassD = class   fLogger : Tlogger;  end; These objects I use directly in the code: var  ObjectA : TClassA;  ObjectB : TClassB; ObjectA and ObjectB create their own separate workgroups, and I would like all classes in the group to use the same fLogger instance. I would like to create two instances of TLogger: first for objects: ObjectA, fWorkClass1, fWorkClass2 second for object: ObjectB, fWorkClass3, fWorkClass4 How to register and get from Spring4D? A: [Archive.is] [IoC and DI] Specific instances for object groups – Google Groups Honza Rameš Hi Jacek, I’d recommend using named injections. (Stefan has some surprises that might allow you to achieve similar functionality differently, stay tuned for 1.3 ;-) ). Honza Stefan Glienke You can write your own resolver that handles TLogger and injects the same instance based on some criteria (like a Logger(‘groupname’) attribute on your injection target or something like that) Q: [WayBack] How to debug resolver issues in Spring4D?… – Jacek Laskowski – Google+ How to debug resolver issues in Spring4D? When in constructor occur unregistered type parameter (or registered, but uncompletly – without register his constructor parameters types), Spring creates the object with a bad constructor (without parameters, come from base class), but does not warn about it! And an unfinished object is created, with nil in the key fields. How to avoid this, how to detect it? A: Baoquan Zuo It also happened to me yesterday, in my case, it was caused by a RTTI directive which prevent Spring container locating constructor in component type as compiler didn’t emit them. I wanted to post in the group about adding trace log and warnings about possible errors. Jacek Laskowski In my case class has interface, but I register only class without explicitly register interface (RegisterType<TMyClass>) and container found and register only interface, and when I try resolve class then class not found. After correct code to RegisterType<TMyClass, TMyClass> problem disappear. But trace log would by very useful! Stefan Glienke+1 There is the unit [WayBack]Spring.Container.ActivatorExtension which has a container extension that prevents the container to fall back on the parameterless ctor. Jacek Laskowski +Stefan Glienke You mean [WayBack] TActivatorInspector? How to use it? Stefan Glienke Add the extension to the container. Q: [WayBack] Spring resolver problem… I try resolve factory method (previously registered in container) and I get compile error… – Jacek Laskowski – Google+ Spring resolver problem… I try resolve factory method (previously registered in container) and I get compile error: {$M+} TCompaniesManagerFactory = reference to function(const aAuthKey : RAuthKey) : ICompaniesManager; {$M-} var lCompaniesManagerFactory : TCompaniesManagerFactory; begin lCompaniesManagerFactory := Container.Resolve<TCompaniesManagerFactory>; // <- line with error Error: [dcc32 Error] E2010 Incompatible types: 'TCompaniesManagerFactory' and 'Procedure of object' ps. I know about composition root and others IoC rules… please tell me why I get compile error, types are compatible A: Stefan Glienke+4 Put parentheses on your call. When assigning a function call result to an anonymous method variable it does not consider calling the method to get an assignment compatible result. Most simple case: uses   System.SysUtils; function GiveProc: TProc; begin end; var   p: TProc; begin   p := GiveProc; // <- E2010 - write GiveProc() and it works end. Q: [WayBack] Spring4D, register factory… default parameters… – Jacek Laskowski – Google+ Sprin4D, register factory I have a class that implements the interface: TMyClass = class(TInterfacedObject, IMyInterface) public constructor Create(ParamA : string; ParamB : Integer; ParamC : Boolean); end; and the factory: TMyInterfaceFactoryA = reference to function(ParamA : string; ParamB : Integer; ParamC : Boolean) : IMyInterface; which I register in the spring: Container.RegisterType<IMyInterface, TMyClass>; Container.RegisterFactory<TMyInterfaceFactoryA>; Then I resolve the factory and create an interface, it works ok. But I would like a second factory that will always give ParamC a constant value, e.g. True I tried this: TMyInterfaceFactoryB = reference to function(ParamA : string; ParamB : Integer) : IMyInterface; but I get error when resolving: 'Unsatisfied constructor on type TMyClass' How to declare and register such a factory? A … Jacek Laskowski +Stefan Glienke Of course you were right, everything works correctly. The problem for me was the incomplete registration and “losing” by the container of one of the constructors. Is it possible to force Spring to report an unknown, unregistered type used in the constructors? At the moment, the report is poor, with a complex hierarchy of classes and extensive constructors a lot of time is lost in searching for missing registrations :-(Eg.classes:TUnknownClass = class end;TExampleClass = class public constructor Create(aUnknown : TUnknownClass); end;{$M+} TExampleClassFactory = reference to function : TExampleClass; {$M-}registrations:aContainer.RegisterType<TExampleClass>; // >>>>>> missing TUnknownClass type registration aContainer.RegisterFactory<TExampleClassFactory>;usage: var lExample: TExampleClass; begin lExample := aExampleClassFactory(); and error: 'Unsatisfied constructor on type: ss.Framework.Base.SafeQueryProvider.TExampleClass' There is only information WHERE is missing and not WHAT. Would it be possible to detect the lack of TUnknownClass registration during the TExampleClass class registration and add this fact in the message? I lost a few hours to look for such details, and if Spring were to report it would be wonderful :-) Stefan Glienke “Would it be possible to detect the lack of TUnknownClass registration during the TExampleClass class registration and add this fact in the message?” No, because order of registration does not have to be like that, can easily register TUnknownClass after that or provide it by some other way. Proper ctor to be called are currently determined at resolve time. Even when calling container.Build it currently is not possible to determine that because type registrations are only processed after each other. For that to work at that point it would need to do a second run checking and selecting ctors after all types are known to the container. It even is something that I want for quite some time because that would improve resolve performance significantly because it can already build a plan of what to create without determining that over and over. What we are doing at work is putting some information out via the ILogger interface inside the type resolver so we can see in the log what ctors it inspects and which it picks (or does not). That being said I have been planning quite some changes for 1.3 that also touch on this topic because once your object graph gets huge using the container requires some way of diagnostic possibilities. But the curse of the current flexibility of the container makes this not so easy as there are so many corner cases and exceptional use cases that are all valid that I don’t want to break (or at least be aware of to put them into some breaking change list and provide alternative ways to solve the task) Jacek Laskowski +Stefan Glienke Ok, it does not have to be checked at the registration stage or even Build. It would be enough for the resolver, in the place where it analyzes the available constructors, to detect the type that is not registered, and then that this information would be passed higher and if an exception occurs, its message would contain information about this unknown type. In general, I would like to get info about the fact that the resolver does not know the TUnknownClass type when trying to create a TExampleClass object. That’s all. I know it’s not trivial :-) Thanks for you works, I waiting for S4D 1.3 Q: [WayBack] Spring4D IoC and specific singleton… – Jacek Laskowski – Google+ Spring4D IoC and specific singleton I have a generic interface to write data to the database: IDBStorer. This interface can write data to any pre-defined table (generates inserts and updates). I would like the group of objects that saves, for example, orders, to use one instance of this interface, but configured to store orders. Completely in other place, another group of objects saves, for example, car routes, also uses the IDBStorer interface, but with a completely different configuration. Therefore, I would need to resolve the interface from the factory using some type of “order” or “route” and to get the same instance for each “route” request, but different than when I resolve for “order”. Something like this: OrdersStorer := Container.Resolve<IDBStorer>.NamedSingleton('orders'); RouteStorer := Container.Resolve<IDBStorer>.NamedSingleton('route'); or better by factory: TStorerFactory = reference to function(aStorerIdentifier : string) : IDBStorer; Container.RegisterFactory<TStorerFactory>.AsNamedSingleton; OrderStorer := StorerFactory('orders'); OrderStorer2 := StorerFactory('orders'); RouteStorer := StorerFactory('route'); and I get one instance IDBStorer per unique string, so OrderStorer is equal in this case OrderStorer2 (because resolved by this same unique identifier ‘orders’) Is it possible? A Stefan Glienke I already answered your question on the forum. If you dont like the multiple registrations per “key” for the singletons then use the most obvious: a dictionary where you put in your instances per key and fetch them from there which you can abstract just fine with a factory(key Jacek Laskowski It looks like I have to write my own LifeTimeManager and register the type with this manager, is this a good clue? Jacek Laskowski +Stefan Glienke Where should I put this dictionary? I would like to use the benefits of Spring and entrust him with managing such things. Perhaps in LifetimeManager, similar to TSingletonPerThreadLifetimeManager? Stefan Glienke+1 Do whatever you want but a DI container is not a multipurpose swiss army knife design pattern. It is for creating object graphs. And your object graph by definition has 2 (or more) different instances of IDBStorer instances for a given key (string, or type of object it handles or whatever). The definition of your object graph is what happens in the registrations. As you can see in my example that I gave you I am exactly doing that “using the benefits”. I am putting 2 different registrations (in the example they look the same except their name). Now you could even imagine that the one gets also other dependencies passed than the second (maybe the one needs a TOrderValidator passed as IValidator and the other needs a TRoutesValidator – can easily put that in the registrations and model your object graph). Or one day you find out that you cannot use the same implementation at all for those two and you can easily change that by switching the registrations for one or both to not use the same implementing class but different ones. Everything else is hack that will fall onto your feet sooner or later. Jacek Laskowski+1 +Stefan Glienke Yes! I calmly rethinked about what you wrote, you are absolutely right! Yesterday I thought I was not understood, but it is I who complicate the simple things very much. I forgot about KISS. Thanks for comment. Jacek Laskowski+1 +Stefan Glienke One more question: I do not want to use the IDBStorer interface directly in the constructors of other classes, but I want to use the factory method. How to declare and register a factory to get the same effect? TDBFactory = reference to function (aSingletonIdentifier: string): IDBstorer; Stefan Glienke+1 RegisterInstance<TDBFactory>(function(aSingletonIdentifier: string): IDBStorer begin Result := container.Resolve<IDBStorer>(aSingletonIdentifier); end); A. Bouchez If you use singletons, why not just use a global variable? I don’t like singletons for sure. ;) Stefan Glienke+4 +A. Bouchez Singleton in DI means not the same as in the design pattern. It means that it is ensured that there is only one instance every time I ask for this as a dependency but not a new instance each time. And the subtle but important difference is that the singletoness is not baked into the class itself but controlled by the container and how you configure things. A. Bouchez+1 +Stefan Glienke You are right. I remember now – I already made this confusion some time ago… same naming is IMHO wrong. “Shared” or “Common” could be less confusing for sure. In our framework we use “sicShared” for such an instance livetime. Stefan Glienke+1 +A. Bouchez I did not invent the naming but it is called like that in most DI frameworks. Being really pedantic though I would say that it is an implementation detail of the pattern that is the bad thing and when you do DI the implementation of it is good as it is not coupled to the core responsibility of the class and not part of the class itself but of the mechanism that creates them. The Spring4D forum thread: [Archive.is] Concrete instance of singleton – like a multiple singleton? – Google Groups Jacek Laskowski I have an ISomething interface. I would like a certain group of objects to use a specific instance of ISomething (A), and another group of another ISomething (B) instance. So there is one interface, one implementation, but two instances of this interface are created, which many other objects use. How to register this interface (maybe with identifier?) in the container and how to resolve instance A or B via the factory method? Philipp Schäfer As far as I am aware, you can only name the registration and overwrite the resolving mechanich of each and every depend type (by specifying the named value and nil for the other constructor parameters). This specification is made during the registration phase. I do not recall the exact method name. This will be improved in upcoming versions. Another possibly more simple approach might be to derive two interfaces from ISomething with no further method. And register implementation A and B as singletons to these derived interfaces. If you want to dive really deep you could influence the resolving process by a container extension. We do this for something else in one of our projects. This takes probably the most effort and might be subject to changes in updates. Sorry that I talk mostly out of my head here, as I am on mobile only. {$APPTYPE CONSOLE}   uses   Spring.Container,   System.SysUtils;   type   ISomething = interface     ['{829E67EE-EA29-4D90-8CD3-558DB168F150}']   end;     TSomething = class(TInterfacedObject, ISomething)   end;     TCompBase = class   private     fSomething: ISomething;   public     constructor Create(const something: ISomething);     property Something: ISomething read fSomething;   end;     TCompA = class(TCompBase);   TCompB = class(TCompBase);   TCompC = class(TCompBase);   constructor TCompBase.Create(const something: ISomething); begin   fSomething := something; end;   var   a,b,c: TCompBase; begin   GlobalContainer.RegisterType<ISomething, TSomething>('somethingA').AsSingleton;   GlobalContainer.RegisterType<ISomething, TSomething>('somethingB').AsSingleton;   GlobalContainer.RegisterType<TCompA>.InjectConstructor(['somethingA']);   GlobalContainer.RegisterType<TCompB>.InjectConstructor(['somethingB']);   GlobalContainer.RegisterType<TCompC>.InjectConstructor(['somethingB']);   GlobalContainer.Build;   a := GlobalContainer.Resolve<TCompA>;   b := GlobalContainer.Resolve<TCompB>;   c := GlobalContainer.Resolve<TCompC>;   Writeln(a.Something = b.Something);   Writeln(a.Something = c.Something);   Writeln(b.Something = c.Something); end. Jacek Laskowski I can’t do this on two interfaces or two registrations. In fact, these groups of objects using one singleton can be much more. I will describe it specifically.I have a generic interface to write data to the database: IDBStorer. This interface can write data to any pre-defined table (generates inserts and updates). I would like a group of objects that saves, for example, orders, to use one instance of this interface, but configured to store orders. Completely in other place, another group of objects saves, for example, car routes, also uses the IDBStorer interface, but with a completely different configuration.Therefore, I would need to resolve the interface from the factory using some type of “order” or “route” and to get the same instance for each “route”, but different than when I resolve for “order”.Something like:OrdersStorer := Container.Resolve<IDBStorer>.NamedSingleton('orders'); RouteStorer := Container.Resolve<IDBStorer>.NamedSingleton('route');or better by factory:TStorerFactory = reference to function(aStorerIdentifier : string) : IDBStorer; Container.RegisterFactory<TStorerFactory>.AsNamedSingleton;OrderStorer := StorerFactory('orders'); RouteStorer := StorerFactory('route');and I get one instance IDBStorer per unique string.Is possible?     –jeroen
Read More

FMX Line Angle Demo

 A simple demo showing how to create a GUI with FMX to let the user draw two intersecting lines and then compute and show the angle between the two lines. The use has to click on 3 points: the point where the lines intersect, the point where the first line (red) ends and the point where the second line (green) ends. The user interface is updated in real-time following mouse movements. Full
Read More

TMS WEB Core for Visual Studio Code v1.1 released

We are excited to announce the immediate availability of TMS WEB Core for Visual Studio Code v1.1 that now enables developing cross-platform Electron desktop apps and PWA’s. This is a new milestone in the development of RAD component Object Pascal language based web development. The key differentiators of TMS WEB Core for Visual Studio Code are:

  • RAD component based development from the free Visual Studio Code IDE
  • RAD designer using web technology, enabling live, wysiwyg design-time rendering
  • Development directly from Windows, macOS and Linux desktop machine
  • Rich eco system of web related development extensions for the IDE
  • Modern IDE with multiview editing, direct high-DPI/retina support

With TMS WEB Core for Visual Studio Code v1.1, we complete the three targets that TMS WEB Core offers. In the new v1.1, we introduce next to classic web client applications the Electron application target and PWA target.

Electron

The first new target is Electron applications. Electron is a framework that enables to create compiled applications for Windows, macOS and Linux using web technology for rendering and execution of the application. The Electron framework is fully cross platform and at application code level there is nothing to take care off in terms of different platforms. Note that it is thanks to the Electron framework that the hugely popular Visual Studio Code IDE runs on Windows, macOS and Linux directly (and recently also Raspberry Pi target was added recently).
As Electron applications run as executables directly on the desktop operating system, this means that extra functionality such as direct local file access, access to all kinds of operating system dialogs (File Open, File Save), toast messages, taskbar notifications, drag & drop support and more … is available. For a TMS WEB Core developer, this is offered through Electron specific components. For direct local or network database access, there are also two dataset components for direct access to mySQL and PostgreSQL.

PWA

The other new target is Progressive web applications. PWA is perhaps the most promising direction for web client application development. A PWA is a responsive web application that can run offline and can be installed on mobile devices (iOS/Android) and also in desktop browsers like Chrome, Firefox, Edge Chromium. After install, your PWA can be started from an icon on the home screen as if it is a native cross platform application. It can run offline and when online, it will still update itself. So, as a developer there are zero concerns about deployment.
With TMS WEB Core for Visual Studio Code v1.1, you simply choose a PWA type from the projects repository and it automatically generates all necessary files for creating a PWA. Everything available for classic web applications and that you learned about it is applicable for the PWA project type.

Summary

With v1.1, the TMS WEB Core target support is completed. As far as core framework is concerned and the target support, TMS WEB Core for Visual Studio Code is now on par with TMS WEB Core on Delphi. Best of all, the projects are 100% compatible, so Visual Studio Code developers can decide to start using Delphi and continue working on a project and vice versa. Or a Delphi developer on Windows can exchange projects with a colleague using Visual Studio Code on macOS, etc…

Availability

TMS WEB Core for Visual Studio Code is available from the Microsoft Visual Studio Code marketplace, so, if you had installed it, it will auto-update. It is also available for manual install as trial version from https://www.tmssoftware.com/site/tmswebcorevsc.asp and for active customers after login on our website under “My Products”.

What’s next

The next big step is installable third party component support. At this moment, 3rd party components can be created and used at runtime but there is not yet support for installing these into the IDE, have the components on the tool palette and see the components at design-time. Work on this is already underway and in our internal development versions, we can confirm that the entire TMS FNC component range runs happily within the Visual Studio Code IDE. Our team works as hard as we can on reaching also this milestone. Stay tuned for this and even more exciting developments happening in the labs right now as we unwrap these!

Read More

Read More

More TMS WEB Core Tips & tricks

Today we want to bring to your attention two totally different TMS WEB Core features. These little tidbits that can bring your TMS WEB Core web client application from good to great. The first is about handling application termination and the second is about getting something more out of TWebStretchPanel.

Application termination

For long, handling web application termination was simple: it was not really handled. When there was a reason to handle it server side, software developers came up with the concept of sessions. In a nutshell, when a user first requests a HTML page from the server, a session is started and typically a session timer runs. If the users requests a page update or performs another request from the user, the session timer is reset. If the user does nothing or worse, closes the browser, the server timer runs and when it reaches a predefined time, for example 20 minutes, the session is considered closed and thus stopped. We have all experienced the consequences. You decide to go and grab a cup of coffee, meet a colleague in the coffee room, have an interesting talk that of course takes longer than expected and you return to your desk, want to continue using your web application and you are greeted with a session timeout and need to login again.

In the world of modern single-page web client applications with stateless REST backend, this is a lot less likely to occur as it is way less likely to have a reason for server side session management. An easy way to look at it, is that the session state is now kept in the client and the web client application will just perform stateless HTTP(s) requests to a backend when data update or retrieval is needed.

And still, even in this much more server resource friendly scenario, developers might have a reason to know when the user closes the web application to save something client or server side. To handle this, modern browsers expose the browser window “unload” and “onbeforeunload” JavaScript event. This event is triggered when the browser window is about to be closed or the user leaves the page via navigation. Other than just handling leaving the web client application, it can also be signalled to the user and a confirmation dialog shown to ask if the user really wants to leave.

In TMS WEB Core, taking advantage of this is really simple. In your TMS WEB Core web client application, handle the main form’s OnBeforeUnload event. If you wish to show a confirmation dialog, return the confirmation message text via the parameter AMessage. Note that in Google Chrome, a confirmation message will be shown when the message is not empty but it will contain the standard Google text. For the reason, see: https://bugs.chromium.org/p/chromium/issues/detail?id=587940

Here is a code extract that shows the concept. A simple string variable will determine whether some action is needed before closing or not. This string s is empty by default but during application execution can be set (here via a button click). When this string is not empty, it is used to show a prompt when the user wants to close the application via the form.OnBeforeUnload event and in the form.Unload event it can be effectively handled to do a last action before unloading.

type
  TForm1 = class(TWebForm)
  public
    { Public declarations }
    s: string;
  end;

procedure TForm1.WebFormCreate(Sender: TObject);
begin
  s := '';
end;

procedure TForm1.WebButton1Click(Sender: TObject);
begin
  s := 'Action needed before leaving';
end;

procedure TForm1.WebFormBeforeUnload(Sender: TObject; var AMessage: string);
begin
  AMessage := s;
end;

procedure TForm1.WebFormUnload(Sender: TObject);
begin
  if (s  '') then
    DoHandleUnloadHere;
end;

The result is this dialog when we try to leave the web application either by closing the browser or navigating away from it:

Stretching the use of the TWebStretchPanel

TWebStretchPanel was designed to show a fixed UI under a piece of UI with variable height. Think of a grid, list control with unknown number of rows, image with unknown size, … TWebStretchPanel comes in handy to automatically deal with this. It is actually a HTML DIV element with two child DIV elements, one with a variable size at the top and one with a fixed size at the bottom. Obviously, as the size of the upper DIV dynamically adapts to its content, the fixed size DIV moves downward automatically. In the Delphi form designer, any control with Top coordinate set to 0 is considered part of the upper DIV, the other controls part of the lower DIV.

To demonstrate this, we have at design-time a TWebListControl with WebListControl.Top = 0 on the TWebStretchPanel and two buttons. Note that the TWebListControl.HeightStyle is set to ssAuto as we want its size to automatically adapt to the number of items it contains. We did also set the WebListControl.ElementPosition to epRelative as we expect this control to be automatically layouted by the browser in this upper DIV. Then there are two buttons of the type TWebBitBtn that are placed in the bottom part of the TWebStretchPanel. Here we set WebBitBtn.ElementPosition also to epRelative as we leave it to the browser to control the position and layout of the buttons. In the button OnClick handler we add code to add or remove items from the list:

procedure TForm1.WebButton2Click(Sender: TObject);
begin
  WebListControl1.Items.Add.Text := 'Item ' + WebListControl1.Items.Count.ToString;
end;

procedure TForm1.WebButton3Click(Sender: TObject);
var
  it: TListItem;
begin
  it := WebListControl1.Items[WebListControl1.Items.Count - 1];
  it.Free;
end;

Now, we want to introduce some extras:

Add Material icons

We add little icons from Google Material Icons to the buttons to have a visual for Add/Remove. Via the Delphi IDE project manager, choose “Manage JavaScript libraries” and add check “Material Icons”. Once checked, we can select the icon to use for the button via the WebBitBtn.MaterialGlyph property. The object inspector shows all possible material icons.

  

Add Bootstrap

To give the buttons some nicer style, we wish to use Bootstrap. Also via the Delphi IDE project manager, choose “Manage JavaScript libraries” and add check “Bootstrap 3.3.7”. We will use this one as it doesn’t have a dependency to jQuery like 4.3.1 has. Once we enabled Bootstrap, we can select a Bootstrap button style for the buttons by setting WebBitBtn.ElementClassName to ‘btn btn-primary’ for example.

Add custom CSS

To give the buttons in the lower part of the TWebStretchPanel a nicer layout, we’ll add some margin to the buttons, remove the focus border and make sure the buttons stay besides each other. To do this, we could have added the CSS in the project HTML file, but for clarify and to show the concept of dynamically adding CSS, it is done here in code:

procedure TForm1.WebFormCreate(Sender: TObject);
begin
  AddCSS('btnmargin','.btnmargin { margin:10px; float:left; outline:none; border:none;} .btnmargin:focus {outline: none;}');
  WebBitBtn1.ElementClassName := WebBitBtn1.ElementClassName + ' btnmargin';
  WebBitBtn2.ElementClassName := WebBitBtn2.ElementClassName + ' btnmargin';
end;

Note that we add the new introduced btnmargin CSS class to the ElementClassName as it contains already the Bootstrap class specifier.

Customize the TWebStretchPanel bottom color

Default the TWebStretchPanel are just two DIV containers within a DIV. We can access these DIV elements easily and therefore also customize these. Just to highlight one additional way TMS WEB Core web client applications can directly interact with any HTML element in the DOM, we have chosen here for educational purposes for yet another technique to set the color of the lower DIV. In the form’s OnShow event, when we are sure the HTML element is in the browser DOM, we access this DIV as the 2nd child of the TWebStretchPanel main DIV container (ElementHandle) and can directly access its style property in code:

procedure TForm1.WebFormShow(Sender: TObject);
var
  el: TJSHTMLElement;
begin
  el := TJSHTMLElement(WebStretchPanel1.ElementHandle.children.item(1));
  el.style.setProperty('background-color','silver');
end;

The result of these little customizations is:

Explorer the wonderful world of TMS WEB Core

Without a doubt, the modern browser has become extremely powerful in many ways and is almost as rich as an operating system by itself.
The possibilities of HTML/CSS are virtually unlimited for the most demanding UI needs and note that these strengths can also be applied to create installable mobile device applications (PWA) or cross-platform desktop applications via the Electron framework (or other ways we will reveal in the near future).

For Object Pascal developers, we have our beloved strongly typed and object oriented language available thanks to the pas2js compiler (with coming soon more powerful than ever Object Pascal language features) and TMS WEB Core adds RAD component based development. And finally, there is a freedom of choice what IDE to use with TMS WEB Core: Delphi, Lazarus or Visual Studio Code. Wanting to explore TMS WEB Core on your Windows, macOS or Linux machine, get the free Visual Studio Code IDE and install TMS WEB Core for Visual Studio Code for it!

Read More

Read More

TMS FNC Planner Editing

Intro

Since the first release, TMS FNC UI Pack has been constantly evolving. Version 3.2 added a lot of great new functionality and new components (https://tmssoftware.com/site/blog.asp?post=695). Today, we wanted to focus on a component that has been there since v1.0: TTMSFNCPlanner.

The TTMSFNCPlanner is a scheduling component with various built-in time-axis options, i.e. a day, week, month, period, half-day period, timeline as well as custom time-axis mode where you can fully control the duration of each timeslot. The TTMSFNCPlanner supports single and multi resource views and can have the time-axis in horizontal or vertical orientation. Even when targeting mobile devices, the TTMSFNCPlanner will automatically use a touch-friendly approach. Today’s blog post focuses on a feature that is essential for an application that uses the maximum potential TTMSFNCPlanner has to offer: editing.

Editing

Editing is divided into 3 parts:

  • Inplace editing
  • Dialog editing
  • Custom editing

Inplace editing

Inplace editing is enabled by default. Clicking in the planner item notes area will start the inplace editor. The default inplace editor is a TMemo, but can be configured to whatever inplace editor you want to use, with the OnGetInplaceEditor event. See the topic “Custom editing” below for an example. After the editor is started, text can be entered, and committed via the F2 key, or by clicking on another part of the planner. Cancelling is done via the Escape key.

Changing the behavior of inplace editing can be done via one of the various properties under Interaction.

Dialog editing

Dialog editing can be enabled by changing the property Interaction.UpdateMode to pumDialog. When doing the same kind of interaction (selecting the item, clicking on the notes area), the dialog will be shown which can fully edit the item. Whereas inplace editing can only edit the notes, the dialog can edit title, notes, start & end time of the item.

There is also support for a built-in recurrency editor dialog, which offers the same basic features as the default dialog, and extends this with recurrency options. This is typically used in combination with a dataset (see planner database demo included in the distribution). To use this dialog editor, you can drop an instance of TTMSFNCPlannerItemEditorRecurrency on the form, assign it to the ItemEditor property and click on the item to show the editor, as you would normally do after setting Interaction.UpdateMode to pumDialog.

Custom editing

For both of the above editing types, customization is possible. Let’s start with inplace editing. We want to create a custom editor that uses a TTMSFNCRichEditor and a TTMSFNCRichEditorFormatToolBar. We start by implementing a custom class wrapper that creates and holds a reference to a set of richeditor related classes for importing and exporting HTML as well as a toolbar and the richeditor itself. The planner item supports HTML and we need a way to convert the HTML coming from the item to the rich editor and vice versa.

type
  TCustomInplaceEditor = class(TTMSFNCCustomControl)
  private
    FHTMLImport: TTMSFNCRichEditorHTMLIO;
    FRichEditor: TTMSFNCRichEditor;
    FRichEditorToolBar: TTMSFNCRichEditorFormatToolBar;
    FScrollBox: TScrollBox;
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

{ TCustomInplaceEditor }

constructor TCustomInplaceEditor.Create(AOwner: TComponent);
begin
  inherited;
  FScrollBox := TScrollBox.Create(Self);
  FScrollBox.Parent := Self;
  FScrollBox.Align := TAlignLayout.Client;

  FRichEditor := TTMSFNCRichEditor.Create(FScrollbox);
  FRichEditor.Parent := FScrollbox;

  FRichEditorToolBar := TTMSFNCRichEditorFormatToolBar.Create(FScrollbox);
  FRichEditorToolBar.RichEditor := FRichEditor;
  FRichEditorToolBar.Parent := FScrollbox;

  FRichEditor.Position.Y := FRichEditorToolBar.Height;

  FRichEditor.Width := FRichEditorToolBar.Width;

  FHTMLImport := TTMSFNCRichEditorHTMLIO.Create(Self);
  FHTMLImport.RichEditor := FRichEditor;
end;


To show the new inplace editor, implement the OnGetInplaceEditor event and return the TCustomInplaceEditor class. When clicking on the item, the TCustomInplaceEditor instance will be created and shown.

procedure TForm1.TMSFNCPlanner1GetInplaceEditor(Sender: TObject; AStartTime,
  AEndTime: TDateTime; APosition: Integer; AItem: TTMSFNCPlannerItem;
  var AInplaceEditorClass: TTMSFNCPlannerInplaceEditorClass);
begin
  AInplaceEditorClass := TCustomInplaceEditor;
end;

As you can see, the TTMSFNCRichEditor does not show the text that was originally visible in the item. We need to import the TTMSFNCPlanner item text as HTML. As the TCustomInplaceEditor is actually too big, we also set the size here so there is enough space available to edit the text and get access to the TTMSFNCRichEditorFormatToolbar.

procedure TForm1.TMSFNCPlanner1AfterOpenInplaceEditor(Sender: TObject;
  AStartTime, AEndTime: TDateTime; APosition: Integer;
  AItem: TTMSFNCPlannerItem; AInplaceEditor: TControl;
  AInplaceEditorRect: TRectF);
var
  c: TCustomInplaceEditor;
begin
  c := (AInplaceEditor as TCustomInplaceEditor);
  c.SetBounds(c.Left, c.Top, c.FRichEditorToolBar.Width + 20, 200);
  c.FHTMLImport.InsertHTML(AItem.Text);
end;

To update the item, after editing the text we’ll need another event: OnBeforeUpdateItem. This event is called after closing the editor. Here we need to convert the text from the TTMSFNCRichEditor to HTML, to import back into the item.

procedure TForm1.TMSFNCPlanner1BeforeUpdateItem(Sender: TObject; AStartTime,
  AEndTime: TDateTime; APosition: Integer; AItem: TTMSFNCPlannerItem;
  var ATitle, AText: string; var ACanUpdate: Boolean);
var
  c: TCustomInplaceEditor;
  sl: TStringList;
begin
  c := (TMSFNCPlanner1.GetInplaceEditor as TCustomInplaceEditor);
  sl := TStringList.Create;
  try
    sl.Text := c.FRichEditor.ContentAsPlainHTML;
    AText := sl.Text;
  finally
    sl.Free;
  end;
end;

As with inplace editors, dialogs can also be fully customized. If the default supported dialogs are not sufficient, you can use a set of events to show a custom dialog. In this sample, the TTMSFNCPlanner shows an overview of cardiologists and patients that need to have surgery. A cardiologist can click on a planner item, and edit it to confirm the patient is successfully operated. To start, we have created a custom dialog.

This dialog is going to be shown instead of the default dialog when editing an item. We are also going to dynamically edit the item based on dialog and vice versa. In this code snippet we are going to hide the remove button, as we don’t want users to remove the scheduled patient we are going to edit.

procedure TForm1.TMSFNCPlanner1AfterOpenUpdateDialog(Sender: TObject;
  AStartTime, AEndTime: TDateTime; APosition: Integer;
  AItem: TTMSFNCPlannerItem);
begin
  TMSFNCPlanner1.GetEditingDialog(AItem.Index).ButtonRemove.Visible := False;
end;

The next step is to link the item to the custom dialog. This makes sure that the properties that are available at item level are displayed in the custom dialog.

function FindChild(AContainer: TControl; AName: String): TControl;
var
  I: Integer;
begin
  Result := nil;
  for I := 0 to AContainer.ControlsCount - 1 do
  begin
    if AContainer.Controls[I].Name = AName then
    begin
      Result := AContainer.Controls[I];
      Break;
    end;
    Result := FindChild(AContainer.Controls[I], AName);
  end;
end;

procedure TForm1.TMSFNCPlanner1ItemToCustomContentPanel(Sender: TObject;
  AItem: TTMSFNCPlannerItem; AContentPanel: TControl);
var
  l: TLabel;
  c: TCheckBox;
  img: TImage;
  b: TColorComboBox;
begin
  l := FindChild(AContentPanel, 'lblPatient') as TLabel;
  l.Text := 'Patiënt: ' + AItem.Title;
  c := FindChild(AContentPanel, 'chkOperation') as TCheckBox;
  c.IsChecked := AItem.DataBoolean;
  img := FindChild(AContentPanel, 'imgPatient') as TImage;
  img.Bitmap.Assign(TMSFMXBitmapContainer1.FindBitmap(AItem.DataString));
  b := FindChild(AContentPanel, 'cboCategory') as TColorComboBox;
  b.Color := AItem.Color;
end;

After editing the item, we also want to save the settings from our custom dialog back into the item.

procedure TForm1.TMSFNCPlanner1CustomContentPanelToItem(Sender: TObject;
  AContentPanel: TControl; AItem: TTMSFNCPlannerItem);
var
  c: TCheckBox;
  b: TColorComboBox;
begin
  c := FindChild(AContentPanel, 'chkOperation') as TCheckBox;
  b := FindChild(AContentPanel, 'cboCategory') as TColorComboBox;
  AItem.BeginUpdate;
  AItem.Color := b.Color;
  AItem.DataBoolean := c.IsChecked;
  AItem.EndUpdate;
end;

Note that we are using custom properties such as Color and DataBoolean, so we can update and edit custom information about our patient.

Last but not least, we need to make sure the planner picks up the dialog when clicking on the item.

procedure TForm1.TMSFNCPlanner1GetCustomContentPanel(Sender: TObject;
  AItem: TTMSFNCPlannerItem; var AContentPanel: TControl);
begin
  if Assigned(AItem) and (AItem.Resource = 1) then
    AContentPanel := Panel1;
end;

We hope this blog post gives you an insight on what is available specifically for editing planner items. There is much more to discover, so check out the demos and documentation.

Read More

Read More

TMS WEB Core for VSC 1.1 beta

We are getting closer to the next milestone of our TMS WEB Core for Visual Studio Code project. So, this is an ideal moment for letting TMS ALL-ACCESS users have access to the TMS WEB Core for Visual Studio Code v1.1 beta that we released today.

New features v1.1 beta

  • Support for creating PWA’s (Progressive Web Applications, i.e. installable and offline usable apps for iOS and Android mobile devices).
  • Support for Electron cross platform desktop apps (Windows, macOS, Linux)
  • In sync with the TMS WEB Core framework latest release v1.5.5.2
  • Lots of further polishing on IDE integration in Visual Studio Code.

Roadmap Q4 2020/Q1 2021

The next big milestone after the v1.1 release will be v1.2 where the highlight will be installable extra components. At this moment, components not installed in the IDE can be used at runtime of course, but the focus of v1.2 will be to offer the capability to install the components on the tool palette and make the components usable on the form designer in the IDE. This huge work is already well underway. The entire TMS FNC components portfolio (TMS FNC UI Pack, TMS FNC Maps, TMS FNC Dashboard, TMS FNC Cloud, TMS FNC Blox) is in on development versions in our R&D team already working from the Visual Studio Code IDE as well. After the IDE infrastructure in the IDE is finished & polished, this will be the v1.2 release. Also for v1.2 we have project templates coming.

Summary

Now is the time to discover what TMS WEB Core for Visual Studio Code can do for you, Object Pascal and RAD component based software developer reaching out to create rich web client applications or create applications with a modern front-end based on web technology.

  • Large number of included visual and non-visual components: With these components, a RAD approach allows you to build solutions fast.
  • Visual data-binding: A data-binding mechanism similar to Delphi VCL data-binding enables to hook-up your client application via client datasets to data sent from a REST API based backend quickly.
  • Use existing or custom HTML web templates: The Visual Studio Code IDE has built-in strong support for editing HTML/CSS and a vast array of extensions. This adds even more power to it. The visual designer shows the pages ”as is” using the templates.
  • Integrate any existing JavaScript library: The underlying pas2js compiler for transpiling Object Pascal code to JavaScript code running in the browser facilitates programmatic access to any existing JavaScript library. This opens up the huge availability of all kinds of easily available web functionality to integrate.
  • Debug using Object Pascal code: All modern debugging capabilities like breakpoints, watches, stepping in code, … can be done in the Object Pascal code base from the Visual Studio Code IDE.
  • Project compatibility with Delphi. Create projects in Delphi and open & work further on these in Visual Studio Code and vice versa.

Get in the front seat today

This new beta is available for registered TMS ALL-ACCESS users. So our VIP users can already test the new features!

Take a head start now and get TMS WEB Core for Visual Studio Code at our launch price starting from 295EUR for a single developer license or download and explore this new ground-breaking product using the trial version!

Read More

Read More

Automated testing Windows applications using Katalon and WinAppDriver

[WayBack] Top 45 Best Automation Testing Tools Ultimate List • Test Automation Made Easy: Tools, Tips & Training Awesomeness A few notes, partially related to Enable your device for development – UWP app developer | Microsoft Docs. One research project I had a while ago, was to see how it was possible to use a generic […] … Read More

Read More

Today Oct 17, tmssoftware.com BV celebrates its 20 year anniversary

Company foundation

On October 17 in the year 2000, the company “tmssoftware.com bvba” was officially founded in Belgium. So, this year 2020, we celebrate on October 17 the 20-year anniversary of the company. After I started developing VCL components in 1995 with the release of Borland Delphi 1, I did this for the first 5 years as first part-time self-employed consultant and later full-time self-employed under the umbrella of “TMS software”. By the year 2000, it became clear that the next step in this process of growth was to found a company, have a separate office, and prepare to hire the first employee.

Official declaration of the creation of the company in the Belgian register

First steps

As Delphi was born and brought Pascal developers RAD component-based development, I quickly realized there was a huge potential in creating components myself to enable me to reuse interesting code among various consulting projects I was doing for companies. I realized that when these components would be of interest to myself, these could probably also have value for other Delphi developers. Fortunately, at that time, there were two websites (Delphi Super Pages and Torry.net) that allowed Delphi developers to share created components with other developers. I was curious to try this out and the very first component released on Torry and Delphi Super Pages was TANIIcon.

This was a functionality I had not seen before from other Delphi developers and the component showed on screen animated cursors. I decided to create this component especially because I had not seen it done before and also because it introduced the challenge to create a component with custom property streaming as well as the creation of a custom property editor to pick and preview the animated cursor at design-time. It was a great experience to learn about the internals of the VCL framework. Meanwhile, for my own internal use in consulting projects, I had been working on a component descending from TStringGrid to add loads and loads of features I was needing over and over again in projects. This became TAdvStringGrid and was the first big component I released in a Shareware version. It was released on Delphi Super Pages and Torry and by 1996, I realized we needed a website. In Belgium, these were the early days of the Internet and it was through the ISP that we could get a limited free space for basic HTML pages. It could be found at http://users.skynet.be/tmssoftware. But of course, it no longer exists now. It was only from 1998 that the domain tmssoftware.com was purchased and all pages were moved to a shared hosted server for this domain. Between 1996 and 1998, it was still non-trivial to handle online payment transactions. It was common for developers to send a payment by cheque to purchase shareware. Fortunately, in 1998, Element5 AG in Germany offered its ShareIt service providing a platform for software developers to handle online payments and I almost immediately jumped on it.

Fast-forward to the year 2000, the amount of work involved with developing, marketing, selling, supporting VCL components had grown into a more than full-time job. So, it was time to structure this into the company “tmssoftware.com bvba” and move to newer and bigger office spaces. And it is this 20-year anniversary we celebrate today.

A technical adventure with software progress and new frameworks

These 20 years feel like a fast, adventurous, exciting rollercoaster ride. It was extremely exciting because in the software development industry, we are blessed with an ever-changing landscape and a non-stop flow of new capabilities and opportunities that come. The first component developments were based on the VCL framework and evolved along with Delphi and the Windows operating system. Around 2002, the IntraWeb framework was introduced and a whole new world of new component development opportunities opened-up. I was excited to be able to develop web applications from Delphi, so I obviously jumped on it and started to develop components for it. But not all new technologies I found worthwhile to work on turned out to be successful for TMS software. Borland launched Kylix, the Delphi version for Linux with the CLX framework and we decided to port several VCL components to it. Sadly, it never took off and we had to abandon this.

In 2011, Embarcadero made a major step with releasing the new FireMonkey framework that brought cross-platform development to Delphi developers. It goes without saying that I was also enthusiast and intrigued by these capabilities, and TMS software shortly after released the first FMX components. Since then, we developed a wide portfolio of FMX products.

And it did not stop there. The latest new developments include the TMS FNC framework and the TMS WEB Core framework. The TMS FNC framework originates from the insight that VCL, FMX, and LCL frameworks were close enough to be able to provide an abstraction layer and write components against this abstraction layer and in the process have the ability to write a single source code base for components that can be used in VCL, FMX, and LCL applications and later also in TMS WEB Core framework based web applications. The TMS WEB Core framework was written from the ground up to provide Object-Pascal RAD component-based web client application development using the pas2js compiler that transpiles the code to JavaScript to make it run in the browser.

These latest framework developments make us particularly proud as these are unique and offer a never seen before advantage to Object Pascal developers to develop feature-rich software faster for virtually any platform that exists.

Our ultra limited anniversary gift for you!

To celebrate our 20th anniversary, we did produce a limited edition of 20 copies only of the TMS FNC Maps book written by our chief evangelist Holger Flick.
TMS FNC Maps is the synthesis of all our latest developments. It is a cross-framework component set as it offers mapping service integration that can be used in VCL, FMX, LCL, and TMS WEB Core applications. It is cross-platform as it can be used on Windows, iOS, Android, macOS, Linux, and the Web. And it adds another dimension: It is cross-service! TMS FNC Maps offers access to a myriad of mapping services going from Google Maps, Open Street Maps, Bing Maps to Tom-Tom, Here, Azure, MapBox, and more coming. The use of a service is only a property setting away. This book is as such the ideal candidate to make this special anniversary color edition from as the maps look so much better in color. Wanting to win one copy of this ultra limited and hand-signed book by our team, leave a comment on thi blog sharing an experiece, a memory, a result accomplished with our components and we will pick winners from there.

A big thank you to family, friends, colleagues and community

This 20-year anniversary could not have been possible without the support, passion, and hard-work from so many people involved:

My grandfather: Thank you for letting me experience the feeling of being in charge of a company and being a great example of work ethic and enjoying life at the same time. You have been a great inspiration in many ways.
My father: Thank you for giving me the first PC you got from work and did not want to use. That started it all.
My parents: Thank you for giving me the education and space to let me be creative and explore my dreams.
My wife: Thank you for believing me and pushing me to become fully self-employed and found a company. Thank you for your patience and for putting up with the many hours I spend with work.
My three wonderful daughters: Thank you for understanding and respecting the silence and concentration needed during the many hours of working and for not always being there.
Wagner Landgraf: Thank you for reaching out to make a partnership and build together on this amazing adventure. Thank you for the endless brainstorms, ideas and helping pushing things forward.
Adrian Gallero: Thank you for being a partner for so long, for the many insights and ideas and for bringing the amazing piece of work FlexCel as flagship product in the TMS family.
Bart Holvoet: Thank you for believing in TMS since its inception and becoming the first employee. Thank you for the not oversee-able amount of work you put into many parts of TMS, its website and many products.
Pieter Scheldeman: Thank you for becoming the second employee and having accomplished amazing, unique, and ground-breaking products. Thank you for always pushing me and the team to the next level.
Masiha Zemaria: Thank you for being the heart and face of the company assisting our customers day-in, day-out with all their needs and questions and for taking care of the public image of the company.
Tünde Keller: Thank you for your curiosity in new technologies and courage to overcome even the most difficult technical challenges. Thank you for creating rock-solid components this way.
Gjalt Vanhauwaert: Thank you for your openness to handle a wide variety of development tasks in the TMS family. From testing, creating demos, adapt components, offering support and now also creating videos for social media.
Roman Kassebaum: Thank you for breaking down any barrier that might exist in the Delphi IDE to let TMS WEB Core shine in it. Thank you for helping me improve my German language and for the many chats about cars and politics.
José Leon Serna: Thank you for the amazing job on bringing the TMS WEB Core framework to Visual Studio Code. Thank you for the opportunity to be able to work together with such a highly skilled, extremely intelligent and – at the same time – pragmatic software developer.
Holger Flick: Thank you for being a TMS fan of the first hour and believing in the potential of the company. Thank you for the top-notch evangelization work you do and for being the critical and blunt voice that pushes us to higher levels.
Bernard Roussely: Thank you for believing in TMS as a partner for offering cryptography components for Delphi developers
Marion Candau: Thanks for all the hard work that goes into the cryptography products.
Roman Yankovsky: Thank you for our cooperation with the respected FixInsight product and for new exciting upcoming developments in the area of GraphQL.
Sergey Gladkiy: Thank you for your exceptional skills combining deep mathematical understanding and programming at the same time resulting in a powerful math & stats library for Delphi users.
Al Gonzalez: Thank you for your trust in our company and for being open to a brand new position for you. I’m looking forward to exciting developments coming
Chad Hower: Thank you for inspiring me to help Delphi reach out to the web with the IntraWeb framework and for the friendship and beautiful times at beautiful beaches.
Detlef Overbeek: Thank you for your relentless efforts to support the Object Pascal community and for the countless hours of brainstorming, inspiration, and thinking out of the box. Thanks for keeping the community alive via the Blaise Pascal Magazine
Mattias Gaertner: Thank you for the amazing job done with the pas2js compiler and for putting up with me asking technical questions over and over again related to the pas2js compiler.
Michael Van Canneyt: Thank you for your brilliant vision and deep technical knowledge and for assisting me so many times.

Many thanks also go to numerous people in the Delphi community. In the first place, many of the former Borland employees like Danny Thorpe, David Intersimone, and Anders Heijlsberg, who shared so much technical insights with me and inspired me to become a better software developer. Thanks for many of the Embarcadero employees still pushing Delphi and that are always helping when I have questions like Marco Cantu, Jim McKeeth, David Millington, Sarina Dupont, Calvin Tang
Thanks to Thierry Laborde, former Embarcadero France director with who we worked together to create the TMS MultiTouch SDK and who laid the foundations of the original TMS VCL WebGMaps products. Thanks to Lino Tadros for believing in us when we created the first IntraWeb user interface component set and with whom we created UI components for ASP.NET and Silverlight. Thanks for the many software book authors that were a source of knowledge and inspiration, in particular Ray Lischner. Thanks for so many nice people in the Delphi community. Thanks to Jens Fudge, Jeroen Pluimers, Glenn Crouch, Cary Jensen, Loy Anderson, Ray Konopka, Sabine Rothe, Matthias Eissing, Andrea Magni, Daniel Wolf, Bob Swart, Filip Lagrou, Pawel Glowacki, Hadi Hariri, Margreet Van Muyden, the EKON conference team … and so many more Delphi community members and luminaries for always ensuring that wherever people gather around Delphi, it feels so good.

A big thank you to you, loyal customer

Thanks to our loyal customers as well. We thank our customers for the trust in our company, our products, and our support services. On an almost daily basis, our short-line communication between the customers and the TMS team leads to product improvements, new product ideas and documentation enhancements. That several of our products are these days rock-solid and feature-rich is a direct result of a symbiotic long-term relationship with customers, some of which have been customers as long as the company exists.

Thanks for everyone not listed here but who played nevertheless a role – big or small – in the 20 year history of the company.

Let passion drive the future

For the next 20 years, I am confident the passion for software development and the warmth of the community will lead to many more exciting products, fruitful collaborations, interesting exchanges with customers, and visions turned into a reality. I am looking forward to many more adventurous loops and wild rides on the software development rollercoaster.

Watch also this related video on Gjalt’s 101:

Read More

Read More

Embarcadero Conference Brazil 2020

O maior evento Delphi do mundo irá acontecer novamente este ano. Mesmo com toda a situação da pandemia do COVID-19, a Embarcadero Conference 2020 irá se realizar no dia 20 de Outubro, em um novo formato, 100% online.


Apesar dos participantes perderem algumas coisas que só acontecem em eventos presenciais, com conversas valiosas e trocas de experiências com outros participantes nos intervalos das sessões, haverá benefícios interessantes nesse novo formato:

  • Taxa de inscrição mais acessível;
  • Você pode participar de onde estiver – sem precisar pegar um avião e reservar um hotel;
  • As palestras serão gravadas, assim os participantes não perderão nenhuma delas!

Note que todas as palestras devem ser ao vivo. Assim, mesmo que elas sejam gravadas para serem vistas depois, escolhendo a palestra a participar trará os benefícios de poder interagir com o palestrante, fazer perguntas, conversar com os outros participantes, e assim por diante.

Assim, aqui estão nossas sugestões para as palestras pra você participar:


9 am – SERVIÇOS NA NUVEM: NÃO COMETA ESTES ERROS! (Wagner Landgraf)

Após anos lidando com desenvolvimento de serviços na nuvem, seja criando aplicações ou frameworks dedicados nessa área, o palestrante mostrará os principais conceitos, segredos, dicas e experiências para a construção de serviços na nuvem em Delphi. É um compartilhamento das experiências reais, problemas reais e sucessos reais, focando nas armadilhas e problemas que podem ocorrer ao longo do desenvolvimento e mostrando as soluções e prevenções para tais.


1 pm – SEU PRIMEIRO CRUD COM TMS WEB CORE (Marcos Moreira)

Será mostrado como configurar o ambiente, criar sua primeira aplicação, e os aspectos para sua distribuição.


3:40 pm – TMS ACADEMIC – THE TMS SOFTWARE ACADEMIC PROGRAM (Wagner Landgraf)

O programa TMS Academic será apresentado – suas motivações, seu futuro e como embarcar neste programa para obter licenças 100% gratuitas e funcionais dos produtos TMS se você for um aluno ou professor!

Visite a página oficial da Embarcadero Conference 2020, registre-se e participe!

The biggest Delphi event in the world is coming again this year. Even with all the COVID-19 pandemic situation, Embarcadero Conference 2020 in Brazil will happen on October, 20th, in a new format, 100% online.

Even though attendants will lose some things, like the great and valuable in-person conversations, there will be some great benefits with this format:

  • More affordable fee;
  • You can participate from where you are – no need to take a plane and book a hotel;
  • Sessions will be recorded so attendants won’t miss any of them!

Note that all sessions are supposed to be live. So even though they will be record, choosing a session to attend will bring you the benefit of interacting live with the speaker, asking questions, chatting with other attendants, and so on.

Thus, here is our suggestions for sessions you could attend:


9 am – CLOUD SERVICES: DON’T MAKE THESE MISTAKES! (Wagner Landgraf)

After years of dealing with cloud service development, whether creating applications or dedicated frameworks in this area, the speaker will show the main concepts, secrets, tips and experiences for building cloud services with Delphi. He will share real experiences, real problems and real successes, focusing on the pitfalls and problems that can occur throughout development and showing the solutions and preventions for them.


1 pm – YOUR FIRST CRUD WITH TMS WEBCORE (Marcos Moreira)

You will be shown how to configure the environment, create your first application, and the aspects for its distribution.


3:40 pm – TMS ACADEMIC – THE TMS SOFTWARE ACADEMIC PROGRAM (Wagner Landgraf)

The TMS Academic program will be presented – the motivations, the future, and how to embark in this program to get 100% free and functional licenses of TMS products if you are a student or a teacher!

Visit the Embarcadero Conference 2020 official page, register and participate.

Read More

Read More

TMS FNC UI Pack v3.2 Revealing some highly anticipated components

We already have an extensive set of powerful and feature-rich UI controls in our TMS FNC UI Pack.
But there is always room for some additional tools to help you with your cross framework and cross platform work. In this new release of our TMS FNC UI Pack we’ve added 5 new components which were requested by you, our community of great developers who see the enormous advantages of components that can be used on VCL, TMS Web Core, FMX and Lazarus with just one code base.

TMS FNC Controls can be simultaneously used on these frameworks:

  • VCL
  • WEB
  • FMX
  • LCL

TMS FNC Controls can be simultaneously used on these operating systems/browsers:

TMS FNC Controls can be simultaneously used on these IDE’s:

New to the TMS FNC UI family

TTMSFNCRichEditorHorizontalRuler

TTMSFNCRichEditor has a ruler control that can be connected to it. This control has the intuitive handling that you are familiar with from the advanced text editors. With this ruler you can easily control the margins of your page and the indentation of your text. And you have the ability to add tabs, which sets the position of your text when the next tab is pressed. This component is a great advantage to get your text document to a higher level as it helps you with the layout of your text.

TTMSFNCSplitter

Our TTMSFNCSplitter has the same behavior as other splitters, but as this is a FNC control, you can use the same component on all the different platforms. No more need to set framework specific properties. Next to this timesaving feature, we have made the appearance customizable to your preferences, so the control can blend in with your application.

TTMSFNCProgressBar

One of the most requested components is the TTMSFNCProgressBar, this provides users with visual feedback about the progress of a procedure within an application. With more than 25 properties to set the appearance and layout of the component, you have a huge range of possibilities to customize your TTMSFNCProgressBar. And by changing the minimum and maximum value, you can easily invert the direction of the progress.

TTMSFNCRating

While we were creating the TTMSFNCProgressBar, we noticed that it might be nice to have a similar control with interaction. Therefor we created TTMSFNCRating. With the use of images (SVGs as well) you can set a scale to give a rating. If you clear the images, the control will look like a TTMSFNCProgressBar but with the ability to interact with it. This can be done by clicking on the value that you want, sliding from the end of the progress to where you want or via your keyboard with the arrow keys.

TTMSFNCWaitingIndicator

An indicator for illustrating an indefinite waiting time for a task that is in progress. You can choose if you want show a progress or if you want circles, squares or images moving around a center bitmap or if you want them to change size. In case you want to show that a form or a panel is currently not available, you can center the waiting indicator over the parent and use an overlay to emphasize this.

If you want to see some other examples or the behavior of the FNC splitter and rating control, you can have a look at the following video:

Read More

Read More

Installing Firebird 3.06 on Ubuntu 18.04.5 LTS

Thanks to my inexperience with the Ubuntu package manager, and my talent for breaking software, I managed to trash my Ubuntu installation recently to the point where it wouldn’t even boot.  It gave me the opportunity to test my backups, and I’m happy to say that re-installing Ubuntu with a restore of data, with some re-installation of apps got me pretty much back to where I was.  I did however, encounter an issue where Ubuntu would not login to the GUI.  Thankfully I eventually found this post, which solved the problem. The original issue started around the installation of Firebird 3.0.5 for Linux. It appeared the installer needed a file libtommath.so.0 which was not present on my distro.  I thought I had gotten it installed properly, then I ran into the infamous “COLLATION UNICODE_CI_AI for CHARACTER SET UTF8 is not installed” error.  I managed to get past that, but when I opened the database in an FMX app using FireDAC in local mode I got an exception “N8Firebird16status_exceptionE”.   FlameRobin would open it without issue.  If I chose Break in the exception dialog it looked for the source to libstdc++.so.6. The exception was in a call to isc_attach_database or isc_dsql_fetch.  I assumed it was an incompatibility between FireDAC and the standard C++ library. It turns out I had gotten myself into a mess trying to get the libtommath file.  I broke some package references and when I tried to fix them, a slew of packages were removed.  I was warned not to continue unless I knew what I was doing, but when has that stopped me?  Also there didn’t seem to be any alternative to fix the package manager’s complaint that things were broken even if everything still seemed functional.  Ah live and learn… This time I tried installing Firebird 3.06 thinking it was newer and might address some of the problems I had encountered….nope.  This time I used a symlink ( sudo ln -sf /usr/lib/x86_64-linux-gnu/libtommath.so.1 /usr/lib/x86_64-linux-gnu/libtommath.so.0 ) to resolve the missing libtommath. Then I got a completely new error in the FMX deployment code.  It attempted to create a hidden folder “/home/<username>/.fmxlinux” which contains “libfmux-1.48.so”.  I did not invoke paserver with sudo so I didn’t have adequate permissions and got an EFCreateError exception with an empty message triggered by line 9345 of System.Classes.  I only mention that because the message should contain the filename being created and the OS error message but it did not. After resolving the permission issue, I re-confirmed that even on my fresh Linux/Firebird install, I still get an exception when attempting to access my database, which of course pertains to the missing collation.  Since I didn’t make note of how I resolved the collation error when I installed 3.05 I can’t be sure what I did, or whether the “resolution”  did not truly work. Reading the “Release notes for Firebird 3.06″ I saw they had upgraded the ICU libraries to v52.1 so I downloaded the package and installed it.  Re-starting Firebird the collation error was resolved and neither FireDAC or FlameRobin reported the “N8Firebird16status_exceptionE” error any longer.  Obviously whatever I did to fix the collation error when I installed Firebird 3.05 was not correct despite the fact I was no longer getting the collation exception. I hope this helps someone else install FireBird 3.06 on Ubuntu/Debian and saves them all the time I spent searching for solutions to the myriad of issues I encountered including my own folly.
Read More

I Just Don’t GetIt

In case you were wondering, GetIt appears to be down at the moment.  I went to take 5 minutes to update a bug report, and I needed to install FmxLinux to do so, only to see:
I guess it will have to wait.  This is the problem of automating everything.  You become reliant on services that […] … Read More

Read More