2010-06-12 12:16:42 -04:00
|
|
|
Writing Simba Extensions
|
|
|
|
========================
|
|
|
|
|
2010-06-13 07:11:24 -04:00
|
|
|
Simba extensions are scripts written for the interpreter that can be embedded into
|
|
|
|
Simba. Purposes vary from updaters to editors.
|
2010-06-12 16:11:31 -04:00
|
|
|
|
|
|
|
.. FIXME link to dtm and bitmap
|
|
|
|
|
|
|
|
How they work
|
|
|
|
-------------
|
|
|
|
|
2010-06-13 07:11:24 -04:00
|
|
|
Extensions are event based. Functions from the extension are called based on external events.
|
2010-06-12 16:11:31 -04:00
|
|
|
|
|
|
|
Extension core hooks
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
Simba offers several core hooks: init, free, attach and detach. These are used
|
|
|
|
to initialize, show, hide and free your extension. GetName and GetVersion are
|
|
|
|
called to retreive the name and version of an extension.
|
|
|
|
|
|
|
|
init
|
|
|
|
~~~~
|
|
|
|
|
|
|
|
Called when the Extension is initialized.
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
procedure init;
|
|
|
|
begin;
|
2010-06-13 07:11:24 -04:00
|
|
|
Writeln('Initialize your extension here.');
|
2010-06-12 16:11:31 -04:00
|
|
|
end;
|
|
|
|
|
|
|
|
If you want to add a button to the menu, do it now.
|
|
|
|
From the SRL updater extension:
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
:linenos:
|
|
|
|
|
|
|
|
procedure Init;
|
|
|
|
begin;
|
|
|
|
MainMenuItem := TMenuItem.Create(Simba_MainMenu);
|
|
|
|
MainMenuItem.Caption := 'SRL';
|
|
|
|
Simba_MainMenu.Items.Add(MainMenuItem);
|
|
|
|
|
|
|
|
MenuCheck := TMenuItem.Create(MainMenuItem);
|
|
|
|
MenuCheck.Caption := 'Check for new SRL';
|
|
|
|
MenuCheck.OnClick := @OnSRLCheckClick;
|
|
|
|
MainMenuItem.Add(MenuCheck);
|
|
|
|
|
|
|
|
MenuUpdate := TMenuItem.Create(MainMenuItem);
|
|
|
|
MenuUpdate.Caption := 'Update SRL';
|
|
|
|
MenuUpdate.OnClick := @OnSRLUpdateClick;
|
|
|
|
MainMenuItem.Add(MenuUpdate);
|
|
|
|
|
|
|
|
AutoUpdate := TMenuItem.Create(MainMenuItem);
|
|
|
|
AutoUpdate.Caption := 'Automatically update';
|
|
|
|
AutoUpdate.OnClick := @SetAutoUpdate;
|
|
|
|
AutoUpdate.Checked := LowerCase(Settings.GetKeyValueDef('AutoUpdate',
|
|
|
|
'True')) = 'true';
|
|
|
|
MainMenuItem.Add(AutoUpdate);
|
|
|
|
|
|
|
|
Timer := TTimer.Create(Simba);
|
|
|
|
Timer.Interval := 5000;
|
|
|
|
Timer.OnTimer := @OnUpdateTimer;
|
|
|
|
Timer.Enabled :=AutoUpdate.Checked;
|
|
|
|
|
|
|
|
started := True;
|
|
|
|
end;
|
|
|
|
|
|
|
|
free
|
|
|
|
~~~~
|
|
|
|
|
|
|
|
Called upon freeing the extension. Usually this means that Simba is closed.
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
procedure free;
|
|
|
|
begin
|
|
|
|
if started then
|
2010-06-13 07:11:24 -04:00
|
|
|
writeln('Free() was called');
|
2010-06-12 16:11:31 -04:00
|
|
|
end;
|
|
|
|
|
|
|
|
From the SRL updater extension:
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
procedure Free;
|
|
|
|
begin
|
|
|
|
if (started) then
|
|
|
|
Timer.Enabled := False;
|
|
|
|
{ Freeing the components is not needed, as they will be freed
|
2010-06-13 07:11:24 -04:00
|
|
|
upon the closure of Simba. }
|
2010-06-12 16:11:31 -04:00
|
|
|
end;
|
|
|
|
|
|
|
|
attach
|
|
|
|
~~~~~~
|
|
|
|
|
|
|
|
Called when your extension has been enabled.
|
|
|
|
|
|
|
|
From the SRL updater extension:
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
procedure Attach;
|
|
|
|
begin;
|
2010-06-12 17:01:42 -04:00
|
|
|
Writeln('From now on, you shall be alerted as to when your SRL is'+
|
|
|
|
+'out of date!');
|
2010-06-12 16:11:31 -04:00
|
|
|
MainMenuItem.Visible := True;
|
|
|
|
Timer.Enabled := AutoUpdate.Checked;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
detach
|
|
|
|
~~~~~~
|
|
|
|
|
|
|
|
Called when your extension has been disabled. (This is not the same as freeing)
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
Procedure Detach;
|
|
|
|
begin
|
|
|
|
Timer.Enabled := False;
|
|
|
|
MainMenuItem.Visible := False;
|
|
|
|
end;
|
|
|
|
|
|
|
|
GetName
|
|
|
|
~~~~~~~
|
|
|
|
|
|
|
|
Called when Simba requests the name of your extension.
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
function GetName : string;
|
|
|
|
begin;
|
|
|
|
result := 'SRL Updater';
|
|
|
|
end;
|
|
|
|
|
|
|
|
GetVersion
|
|
|
|
~~~~~~~~~~
|
|
|
|
|
|
|
|
Called when Simba requests the version of the extension.
|
|
|
|
|
|
|
|
.. code-block:: pascal
|
|
|
|
|
|
|
|
function GetVersion : string;
|
|
|
|
begin;
|
|
|
|
result := '1.0';
|
|
|
|
end;
|
|
|
|
|
|
|
|
More extension hooks
|
|
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2010-06-12 17:21:37 -04:00
|
|
|
The following hooks are called upon if the event that the name describes has
|
|
|
|
happened.
|
2010-06-12 17:01:42 -04:00
|
|
|
|
|
|
|
.. code-block:: pascal
|
2010-06-12 16:11:31 -04:00
|
|
|
|
2010-06-12 17:01:42 -04:00
|
|
|
EventHooks: Array [0..8] of TEventHook =
|
|
|
|
( (HookName : 'onColourPick' ; ArgumentCount : 3),
|
|
|
|
(HookName : 'onOpenFile' ; ArgumentCount : 2),
|
|
|
|
(HookName : 'onWriteFile' ; ArgumentCount : 2),
|
|
|
|
(HookName : 'onOpenConnection'; ArgumentCount : 2),
|
|
|
|
(HookName : 'onScriptStart' ; ArgumentCount : 2),
|
|
|
|
(HookName : 'onScriptCompile' ; ArgumentCount : 1),
|
|
|
|
(HookName : 'onScriptExecute' ; ArgumentCount : 1),
|
|
|
|
(HookName : 'onScriptPause' ; ArgumentCount : 1),
|
|
|
|
(HookName : 'onScriptStop' ; ArgumentCount : 1));
|
|
|
|
|
|
|
|
For the exact arguments to all these functions, refer to
|
|
|
|
:ref:`extension-example-code`.
|
2010-06-12 16:11:31 -04:00
|
|
|
|
|
|
|
onOpenConnection
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
onWriteFile
|
|
|
|
~~~~~~~~~~~
|
|
|
|
|
|
|
|
onOpenFile
|
|
|
|
~~~~~~~~~~
|
|
|
|
|
|
|
|
onColourPick
|
|
|
|
~~~~~~~~~~~~
|
|
|
|
|
|
|
|
onScriptStart
|
|
|
|
~~~~~~~~~~~~~
|
|
|
|
|
2010-06-13 07:11:24 -04:00
|
|
|
Special Cases
|
|
|
|
~~~~~~~~~~~~~
|
2010-06-12 17:01:42 -04:00
|
|
|
|
|
|
|
Multiple extensions hooking onto the same event
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
So what happens when multiple extensions hook onto the same event/hook?
|
|
|
|
|
|
|
|
The behaviour is currently defined, but prone to change in the near future.
|
2010-06-13 07:11:24 -04:00
|
|
|
Currently all extensions are called in the order they were loaded.
|
2010-06-12 17:01:42 -04:00
|
|
|
|
|
|
|
The behaviour will probably change to something like the following:
|
|
|
|
|
2010-06-13 07:11:24 -04:00
|
|
|
In the order they were loaded, call any available extensions. The first
|
|
|
|
extension to return non-zero terminates the calling loop.
|
2010-06-12 17:01:42 -04:00
|
|
|
|
|
|
|
Pitfalls
|
|
|
|
--------
|
|
|
|
|
|
|
|
Extensions can be very dangerous in the sense that they run on the main thread
|
2010-06-13 07:11:24 -04:00
|
|
|
of Simba, it is very easy to crash Simba or make it hang. There is
|
2010-06-12 17:01:42 -04:00
|
|
|
no way to prevent this, so make sure to check what you're doing before you try
|
2010-06-13 07:11:24 -04:00
|
|
|
your own (or someone else's) extension.
|
2010-06-12 17:01:42 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. _extension-example-code:
|
2010-06-12 16:11:31 -04:00
|
|
|
|
|
|
|
Example code
|
|
|
|
------------
|
|
|
|
|
2010-06-12 17:01:42 -04:00
|
|
|
Example code for most hooks:
|
2010-06-12 16:11:31 -04:00
|
|
|
|
|
|
|
.. literalinclude:: extraextensionhooks.sex
|
|
|
|
:language: pascal
|
|
|
|
:linenos:
|
|
|
|
|
2010-06-12 17:01:42 -04:00
|
|
|
.. note::
|
2010-06-12 12:16:42 -04:00
|
|
|
|
2010-06-12 17:01:42 -04:00
|
|
|
If you need more examples, you can always look at the Extensions in the
|
|
|
|
Simba git repository.
|