Fresnel and the LCL
Fresnel does not use the LCL, but it can work together with it. This was one of the goals of Fresnel from the start: it must be possible to move an existing application to Fresnel step by step, one form at a time. Rewriting everything at once is too big a step for most applications.
Three ways to combine them
Fresnel controls on an LCL form
Put a TFresnelLCLControl on an LCL form. It holds a complete Fresnel viewport, with its own stylesheet and its own tree of Fresnel elements.
Fresnel forms in an LCL program
With the FresnelLCL package, Fresnel uses the LCL as its backend. Fresnel forms then open as normal windows, next to the LCL forms of your program.
A pure Fresnel program
No LCL at all: the Fresnel package talks to the operating system directly. This is the end goal of a migration, and the simplest structure.
The Lazarus form designer uses the second way: Lazarus is an LCL program, and it shows your Fresnel forms with the LCL backend.
Fresnel controls on an LCL form
This is a normal LCL program (Interfaces, Forms). The main form creates a TFresnelLCLControl,
gives it a stylesheet, and puts Fresnel elements in it:
uses
Forms, Controls, Fresnel.LCLControls, Fresnel.DOM, Fresnel.Controls;
procedure TMainForm.FormCreate(Sender: TObject);
var
lHost: TFresnelLCLControl;
lBody: TBody;
lLabel: TLabel; // this is Fresnel.Controls.TLabel, not the LCL label
begin
lHost:=TFresnelLCLControl.Create(Self);
lHost.Align:=alClient; // an LCL control, so LCL properties
lHost.Viewport.Stylesheet.Text:='body { padding: 12px; } label { color: teal; font-size: 20px; }';
lHost.Parent:=Self;
lBody:=TBody.Create(Self); // from here on, Fresnel elements
lBody.Parent:=lHost.Viewport;
lLabel:=TLabel.Create(Self);
lLabel.Caption:='Hello from Fresnel, inside an LCL form';
lLabel.Parent:=lBody;
end;When both the LCL and Fresnel units are in the uses clause, some class names exist twice (TLabel, TButton, …).
Use the unit name to say which one you mean, for example Fresnel.Controls.TLabel or StdCtrls.TLabel.
The demos in demo/lclcontrol of the Fresnel sources show complete programs.
Differences you will notice
Most things in Fresnel work as you expect from the LCL. These are the differences you will meet first:
| Topic | LCL | Fresnel |
|---|---|---|
| Position and size | Left, Top, Width, Height | CSS (width, height, flexbox, grid). Only the form has FormLeft, FormTop, FormWidth, FormHeight. |
| Alignment | Align, Anchors, BorderSpacing | CSS: display: flex, flex, gap, margin, padding |
| Colors and fonts | Color, Font, ParentFont | CSS: color, background-color, font-family, font-size, … |
| Hiding a control | Visible | CSS display or visibility, for example by adding a CSS class |
| Click and mouse events | procedure(Sender: TObject) | procedure(Event: TAbstractEvent): the sender is Event.Sender |
| Other events | TNotifyEvent | often still TNotifyEvent, for example OnChange and OnCreate |
| More than one handler | not possible | AddEventListener(evtClick, @MyHandler) |
| Text of an edit | TEdit.Text | TEdit.Value, like in HTML |
| Panels | TPanel | usually a TDiv with a CSS class; TPanel exists for a panel with a caption |
| Data-aware controls | TDBEdit, TDBGrid, … | the normal controls, connected to a dataset by a mediator |
| Units | StdCtrls, ExtCtrls, ComCtrls, … | Fresnel.Controls, Fresnel.Edit, Fresnel.ComboBox, Fresnel.Tabs, Fresnel.Menus, Fresnel.Dialogs, … |
Porting an application
A good way to port an LCL application:
- Keep the program an LCL program at first, and add the
FresnelLCLpackage. - Port one form at a time. Replace the controls, and move the layout and colors to CSS.
Use CSS classes for roles (
toolbar,row,caption), so that one stylesheet serves all forms. - Leave the colors to the Fresnel theme where you can. Then light and dark mode work automatically.
- When the last LCL form is gone, switch to the
Fresnelpackage and remove the LCL. Your program now talks to the operating system directly, and can also be compiled for the browser.
The time tracker of the Styling with CSS page is an example of a real program that was ported from the LCL. It no longer uses any LCL code.