Now that we have covered the basics of object-oriented programming in PicoLisp, we can finally start with the PicoLisp GUI framework!
What is the PicoLisp GUI framework?
The PicoLisp GUI framework is a set of objects and classes that allow a very efficient and simplified way to define user interactive forms.
They are organized within the form
function and sent to the server via POST
. The POST
is always redirected back to the current page and is triggered by a button press. As we will see, a button's action code can do almost anything: Read and modify the contents of input fields, communicate with the database, display alerts and dialogs, or even fake the POST request to a GET, with the effect of showing a completely different document.
Checking out the source code
The PicoLisp GUI framework is defined in the library form.l
. You can find it in the lib
-Folder of your PicoLisp installation (or type $ locate "lib/form.l"
in your terminal). The framework is organized in classes: Each GUI element has its own class, and we can modify and extend its behaviour by using Prefix-Classes.
The library also has its own documentation, available at https://software-lab.de/doc/form/form.html.
Before we dive into the theory, let's take a look at an example - our previously defined first Name, last Name
-example.
(setq *Css '("@lib.css" "bootstrap.css"))
(app)
(action
(html 0 "Simple Session" *Css NIL
(form NIL
(gui 'a '(+TextField) 30 "First Name")
(<br>)
(gui 'b '(+TextField) 30 "Last Name")
(gui '(+Button) "Send" ) ) ) )
This is the output we get:
By typing Ctrl-U
in the browser (Firefox), we can also view the source code.
As you can see, we have two <input type="text">
fields with name *Gui:1
and *Gui:
, with id2-1
and id2-2
, and an <input type="submit"
with name *Gui:-3
and an id i2--3
.
The input fields are surrounded by a <form>
-tag with method=post
and an action=<some auto-generated link>
. If we fill in the form and click on "Send", we see that the URL changes to http://localhost:<new-port>/<action-link>
.
So far so good, but how does it work? Let's review again the source code and check what functions we have: action
, html
, form
and gui
.
(action
(html
(form NIL
(gui 'a '(+TextField) 30 "First Name")
... ) ) )
We will go through it step by step with help fo the form library reference.
The action
function
The top function is action
. From the documentation, we learn that it's "only" a wrapper function:
(action Prg)
Top level wrapper function for the form event handling. Typically contains one or several calls to
form
.
The form
function
Then we get to the form
function, which is the wrapper function for the form elements.
The gui
function
Inside form
, we can find many calls to a function called gui
. gui
is only defined inside a form
function and takes the following parameters:
- an alias name for the component (optional)
- a list of classes that define the GUI-element, for example
+TextField
- additional arguments as needed by the constructors of these classes.
All gui-classes are subclasses of the abstract class +gui
. We can list them all by viewing the dependency tree of +gui
with (+dep 'gui)
:
: (dep '+gui)
+gui
+Img
+field
+Radio
+TextField
(...)
+Button
(...)
-> +gui
Let's take a closer look at +TextField
and +Button
.
The +TextField
class
The +TextField
class can be defined by several arguments:
-
(gui '(+TextField))
: Plain HTML text is created. -
(gui '(+TextField) 10)
: A text field of length 10 is created. -
(gui '(+TextField) 10 4)
: A text field of length 10 and 4 lines is created. -
(gui '(+TextField) '("Value 1" "Value 2" "Value 3"))
: a drop-down selection. -
(gui '(+TextField) '("Value1" "Value2" "Value3") "Please choose: ")
Strings are used as labels.
In rendered form, it looks like this:
The +Button
class
A +Button
takes several arguments as well:
- A label, which may be either a string or the name of an image file,
- An optional, alternative label which is shown when the button is disabled,
- An optional executable expression.
The button works as submit
-element that sends the form data via POST
and causes the reloading of the page with updated data.
Accessing the data
Now we come to an important point: where can we find the data that we have collected?
If you remember the Object-Oriented programming introduction, you might remember that we can get specific properties of an object with the :
function. All GUI-elements have a property called home
which contains the current form, a function val>
that returns the current value and a function set>
that sets the current value.
Let's take again our textfield example from the beginning:
(form NIL
(gui 'a '(+TextField) 30 "First Name")
... )
We can find its content by getting the home
property from our current form, and then return its property a
(which is our +TextField
-object):
(: home a)
To get its value:
(val> (: home a))
Now let's modify our button so that it prints the content of a
when we press it. Printing to standard error is possible using the msg
function.
(gui '(+Button) "Print" '(msg (val> (: home a)))
If we now enter our text into the textfield and press the button, we see a line in the terminal where the server is running:
: "hello!"
Instead of referencing by alias names, we can also use the relative position of the GUI element, which can be more convenient. For example, in order to access the text of the previous element, we can use (field -1)
.
(gui '(+Style +TextField) "mb-2" 30 "Enter your text: ")
(gui '(+Button) "Print" '(msg (val> (field -1)))
Wrap-up
The example showed how to create HTML forms using the PicoLisp GUI framework.
By calling a form
function within action
, the content is created by pre-defined classes. At submission, the form content is automatically re-directed to the current page using POST
. We can access the values in each field by relative position or by alias names.
It might seem a little confusing at the moment, but it will become clearer the more examples we see. In the next post, we will see how to use Prefix-Classes to further style and define those elements.
Top comments (0)