Web Application Programming in PicoLisp: Introducing the GUI framework
Tags: framework, gui, picolisp, webdev
Published: 2022-02-07 14:13:21

Now that we have covered the [basics of object-oriented programming in PicoLisp](https://picolisp-blog.hashnode.dev/picolisp-explored-object-oriented-programming-part-1),  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:

![simplegui.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633010128445/gMyTlUiDO.png)

By typing ``Ctrl-U`` in the browser (Firefox), we can also view the source code. 


![sourcecodegui.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633010276720/psHqefzuX.png)

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](https://software-lab.de/doc/form/form.html). 


----------------------------

### 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:

![textfiedlclass.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1633177782250/ZXhL67VJR.png)

-------------------------

### 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.

--------------------------

### Sources
- https://software-lab.de/doc/app.html#actionForms  
- https://software-lab.de/doc/form/form.html