LazLILGUI: A LILGUI Implementation for FPLIL and Lazarus ======================================================== 0. Contents ----------- 1. About 2. LazLILGUI API 2.1. TLILGUIControl 2.2. TLazLILGUI 3. Integrating LazLILGUI in Lazarus programs 3.1. Running LIL code with LILGUI functions 3.2. Exposing more controls 4. Contact 1. About -------- LILGUI is a specification for a simple API that allows LIL scripts to create and user interfaces through GUI host programs. It allows scripts to both create their own windows and create user interface elements that can be embedded in existing windows (wherever the host allows) with very minimal code. LILGUI is just a specification and it is up to each host application to implement the necessary functionality and expose the LIL functions to the scripts. LazLILGUI is a reusable implementation of LILGUI based on top of FPLIL and LCL in the form of a component that can be used in Lazarus applications alongside an FPLIL component and optionally a panel or other container control that can receive the controls created in the scripts (this is just a convenience for simple applications - applications can dynamically change the container and even have multiple containers). This readme file describes the classes exposed through the LazLILGUI unit available via the LazLILGUIPackage package for Lazarus. 2. LazLILGUI API ---------------- This section describes the public interface for LazLILGUI. Please note that while the LazLILGUI unit exposes a few types and methods not mentioned in this section, you should not use these types - they are either meant for private use or they are immature APIs that will change in future versions. 2.1. TLILGUIControl -------------- This class represents a LILGUI control and acts as a mediator between LCL and the LILGUI script. If you want to expose additional LCL controls to scripts you must subclass this class. Note that TLILGUIControl is a TComponent subclass and uses the regular component ownership functionality to keep track of the parent and children (so you can simply check which components owned by a TLILGUIControl instance are TLILGUIControl instances themselves to find the children for a control). The available methods are: procedure SetupControl; virtual; Called by TLazLILGUI.CreateGUIControl to setup the control function SetupVar(AVarName: string; AWatch: TNotifyEvent): TLILVariable; Setup a variable bind - AVarName is the variable to bind to and AWatch is a callback that will be called whn the variable is modified function ToValue: TLILValue; Allocates and returns a new LIL value that represent this control procedure SetBounds(X, Y, W, H: Integer); Called to set the bounds of the control procedure GetPreferredSize(PW, PH: PInteger); virtual; Called to return the control's preferred size. Note that both PW and PH might be Nil property GUI: TLazLILGUI read FGUI (read only) The TLazLILGUI instance this control belongs to property Parent: TLILGUIControl (read only) The parent of this control (this is just a convenience property that returns the same value as the Owner one, but type casted to TLILGUIControl) property LCLControl: TControl (read only) The LCL control associated with this control (in some rare cases this might be Nil) property ID: QWord read FID (read only) A unique ID that identifies this control property ControlName: string (read write) The control's name as exposed to the scripts 2.2. TLazLILGUI ---------- This is the most important class for LazLILGUI and provides the "entry" to the LazLILGUI functionality. It must be associated with a single TLIL instance (through the LIL property) that should not be changed through the entire runtime of the application (you can change it but you need to manually destroy and reset the rest of the component state). The available methods are: function ControlByID(ID: QWord): TLILGUIControl; Returns the control that has the given ID or Nil if not found function ControlByName(AName: string): TLILGUIControl; Returns the control that has the given name or Nil if not found function ControlByValue(ALILValue: TLILValue): TLILGUIControl; Returns the control that is represented by the given value (can also be a special string like @name or @@parent) or Nil if not found function CreateGUIControl(ALCLControl: TControl; AClass: TLILGUIControlClass; OverrideParent: TLILGUIControl=nil) : TLILGUIControl; Used as a part of the control creation process from a native LIL function that creates a new control to create and register a TLILGUIControl instance from an LCL control. The third parameter is used internally and you should never use anything else than Nil for it. See section 3.2 for details function NameFromCaption(ACaption: string): string; Returns a name made for the given caption or returns an empty string if the name it would return is already defined procedure AddLCLHost(ALCLHost: TWinControl; MakeCurrent: Boolean); Register an LCL control that will contain LILGUI controls (a "host") so that it can be exposed to the scripts later. If MakeCurrent is true this will become the control that subsequent calls to LILGUI functions will use as the topmost parent container. Note that this will also register a handler for the control's destruction that automatically removes the control and invalidates its subcontrols. When a new host is added, a container LILGUI control is created in it with its Align property set to alClient so that it covers the entire control. This container is set as the current parent (if MakeCurrent is True) and all controls created while the host is set as the current one, will use the container as their parent. The container is placed as a child under the "root" control (see below). If the given host already exists and MakeCurrent is Flase, this call does nothing procedure RemoveLCLHost(ALCLHost: TWinControl); Remove an LCL host added via AddLCLHost and destroy and invalidate the controls it contains property Root: TLILGUIControl read FRoot (read only) The root pseudocontrol, it doesn't really have any real LCL control behind it but is the common parent for all container controls property CurrentParent: TLILGUIControl (read only) The control that is currently being used as the parent for creating new controls - this might be an automatically created container for an LCL host control or a group control created with the "group" LILGUI function property LastControl: TLILGUIControl (read only) The last control that was created property LastLabel: TLILGUIControl (read only) The last label control that was created (but not necessarily the last control) property LIL: TLIL (published read write) The TLIL instance that this control will work with. When this is assigned to a different instance, TLazLILGUI will register the LILGUI functions in it. It is highly recommended to assign this as soon as possible and to avoid switching between different instances property LCLHost: TWinControl (published read write) The current LCL host control. Assigning to this is essentially the same as calling AddLCLHost with MakeCurrent set to True. As a published property, it appears in the form designer so you can set the target container (e.g. a TPanel) visually 3. Integrating LazLILGUI in Lazarus programs -------------------------------------------- Before proceeding, you need to make sure that the FPLILPackage and LazLILGUIPackage packages to Lazarus are installed (make sure the TLIL and TLazLILGUI components are shown in the Misc tab in the Lazarus component palette). 3.1. Running LIL code with LILGUI functions -------------------------------------- To use LazLILGUI simply create a TLazLILGUI object with the LIL property set to a TLIL instance (from FPLIL) and then use TLIL's Parse function to parse LIL code. LIL scripts can now create windows and show dialog boxes using the window and msgbox functions. You can also set the LCLHost property to provide a default container for new controls created outside of a window begin ... window show pair. Setting the property before calling TLIL.Parse can be used to allow for multiple containers. 3.2. Exposing more controls ---------------------- To expose more controls simply register a new LIL function for each control that creates a LCL control (e.g. TMaskEdit) and then creates a TLILGUIControl (or subclass) instance by calling TLazLILGUI.CreateGUIControl with the new control and the class of the TLILGUIControl you want to create. For simple controls (e.g. label) you can use TLILGUIControl directly, however if you want to bind the control to a variable it is a good idea to create a subclass to keep the variable instance. Check the FncLabel for a simple variable-less example and FncSlider (and the TLILGUISliderControl class) for an example of a control that can be bound to a variable. 4. Contact ---------- Kostas Michalopoulos badsector@runtimeterror.com badsectoracula@gmail.com also see http://runtimeterror.com/rep/lilgui