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
