guiserver.lsp

Module index

source download

Module: guiserver.lsp

Functions for programming GUIs and 2D graphics.

Version: 1.40 use text-field as a password field with additional parameter
Version: 1.41 bug fixes for gs:listen and gs:check-event
Version: 1.42 new table UI
Version: 1.43 bug fix in new table UI action parameters
Version: 1.44 fixes in newlisp-edit.lsp
Version: 1.50 doc fixes
Version: 1.51 return value for gs:export
Version: 1.52 fix in run-shell for Java 7 update 21
Version: 1.53 doc fixes
Version: 1.60 new table functions, new naming gs:table-show-row-number
Version: 1.61 more options for gs:scroll-pane added by FdB
Version: 1.62 doc corrections
Version: 1.63 make deprecated gs:table-set-row-number work
Version: 1.70 default comm port with Guiserver are now 64001 and 64002
Version: 1.71 references to /usr/ changed to /usr/local/
Author: LM, 2008, 2009, 2010, 2015, Unya 2012, FdB 2013, LM 2015


This module has been tested on MacOS X 10.5 (Leopard) and Windows XP, both with the Standard SUN Java RE v.1.5 (runtime environment) which came pre-installed on those platforms. On Linux the installation of the original Sun Java Runtime Environment is required the preinstalled GNU Java is not compatible. After installation a soft-link has to be made from the original java executable to /usr/bin/java.



On Windows the MIDI sound features require a soundbank file to be installed. See the description for gs:play-note for details.

What is newLISP-GS

guiserver.lsp is a module for interfacing to guiserver.jar a Java server application for generating GUIs (graphical user interfaces) and 2D graphics for newLISP applications. The guiserver.lsp, module implements a newLISP API much smaller and more abstract than the APIs of the Java Swing libraries which it interfaces with. Because of this, GUI applications can be built much faster than when using the original Java APIs.

Usage

At the beginning of the program file, include a load statement for the module:
 (load "/usr/local/share/newlisp/guiserver.lsp")
 
or on MS Windows:
 (load "c:/Program Files/newlisp/guiserver.lsp")
 
guiserver.lsp expects the server guiserver.jar to be in the directoey specified in the environment variable NEWLISPDIR. When newLISP starts up and this variable is not set yet, it sets it to a default value of /usr/local/share/newlisp on MacOS X and Unix OSs, and to C:\Program Files\newlisp or whatever it finds in the PROGRAMFILES environment variable on MS Windows systems and adding /newlisp to it. This can be overwritten by specifying system wide setting for the environment variable NEWLISPDIR, which normally is set to %PROGRAMFILES%/newlisp on MS Windows. When using the MS Windows binary installer NEWLISPDIR is written to the registry automatically and gets into effect after rebooting.

Architecture of a newLISP GUI application

A GUI application in newLISP is composed of four parts:

initialization - this means starting the newLISP-GS guiserver.jar and initializing communications with it. Only one function call is required to do this.

building widgets - in this step windows, buttons, text fields etc., and all visual aspects of the GUI are described. newLISP newLISP-GS offers a wide range of different control widgets.

defining event actions - in this step all the functions are defined to react to events coming from the GUI as a consequence of button pushes, keystrokes, mouse-movements etc.. These event actions send many commands back to the GUI to change information for the user, popup dialogs etc..

listening for events - the newLISP program sits in a loop waiting for events and dispatching them to the defined event actions. Only one function call is required for this step.


Example

The following example application shows all the essential elements of a newLISP GUI application:

Example:
 #!/usr/bin/newlisp
 ; button-demo.lsp - demonstrate the button control
  
 ; initialization
 (load (append (env "NEWLISPDIR") "/guiserver.lsp")) 

 (gs:init) 
  
 ; describe the GUI
 (gs:frame 'ButtonDemo 100 100 400 300 "Button demo")
 (gs:set-resizable 'ButtonDemo nil)
 (gs:panel 'ColorPanel 360 200)
 (gs:set-color 'ColorPanel (random) (random) (random))
 (gs:button 'aButton 'abutton-action "color")
 (gs:set-flow-layout 'ButtonDemo "center" 2 15)
 (gs:add-to 'ButtonDemo 'ColorPanel 'aButton)
 (gs:set-visible 'ButtonDemo true)
  
 ; define actions
 (define (abutton-action id)
     (gs:set-color 'ColorPanel (random) (random) (random)))
  
 ; listen for incoming action requests and dispatch
 (gs:listen)
  
 ; eof 

Application start

     ./button-demo       ; on MacOS X and Unix
     newlisp button-demo ; on MS Windows
 
By default guiserver.jar uses the ports 64001 and 64002, but this setting can be overwritten either by supplying a port number parameter to the gs:init function or by overwriting the port number from the command-line. newLISP-GS will then use the port number supplied and the number following it:
     ./button-demo 10001       ; on MacOS X and Unix
     newlisp button-demo 10001 ; on MS Windows
 
newLISP-GS guiserver.jar will now use the ports 64001 and 60002. Ports under 1024 should not be used, as many of them are already in use by other OS services and need administrator privileges to use them.

A second method to start a newLISP-GS application starts the guiserver.jar first, which then starts the newLISP application:
     java -jar /usr/local/share/newlisp/guiserver.jar 64001 /usr/home/aUser/MyApplication.lsp
 
A different port number can be used. Port numbers below 1024 need administrator permissions. Optionally a splash screen can be specified as the last parameter:
     java -jar /usr/local/share/newlisp/guiserver.jar 64001 /home/apps/myapp.lsp /local/newLISP128.png
 
The example specifies an image inside guiserver.jar. Any other image path on the local file system can be used.

On MS Windows similar methods can be used replacing the appropriate file paths, but on MS Windows Java jar files can also be treated as executables and executed directly without calling Java explicitly. By default guiserver.jar and guiserver.lsp are installed in c:\Program Files\newlisp\ or any other directory configured on a MS Windows platform using the PROGRAMFILES environment variable:
    "c:\Program Files\newlisp\guiserver.jar" 64001 c:\myprogs\MyApplication.lsp
 
Quotes are necessary when spaces are present in the argument string. The example assumes that newlisp.exe is in the path for executables, and it also assumes that the Windows registry has an association of the .jar file extension with the javaw.exe executable. This association is normally present when a java run-time environment (JRE) is installed in Windows. If this association is not registered, the following method can be used:
    javaw -jar "c:\Program Files\newlisp\guiserver.jar" 64001 c:\myprogs\MyApplication.lsp
 
The quotes are necessary for path-names containing spaces.

Debugging

Tracing commands to newLISP-GS

For debugging purpose put the following directive at the beginning of your application or at the place from where to start tracing.
         (gs:set-trace true)
 
Then start the application from a terminal or command shell window. Now newLISP-GS will output startup, version and connection messages and a trace for each gs:xxs directive as it is received by the newLISP-GS dispatcher:

 newLISP-GS v.0.94
 listening on 64001
 accepted from 0.0.0.0
 connecting to 0.0.0.0 64002
 retrying to connect
 connected
 -> frame MAIN:ButtonDemo 100 100 400 300 QnV0dG9uIGRlbW8= nil
 -> set-resizable MAIN:ButtonDemo nil
 -> panel MAIN:ColorPanel 360 200
 -> set-color MAIN:ColorPanel 0 1 0 0.2
 -> button MAIN:aButton MAIN:abutton-action Y29sb3I=
 -> set-flow-layout MAIN:ButtonDemo center 2 15
 -> add-to MAIN:ButtonDemo MAIN:ColorPanel MAIN:aButton 
 -> set-visible MAIN:ButtonDemo true
 -> set-color MAIN:ColorPanel 0.8401877172 0.3943829268 0.7830992238
 server shut down
 


Text strings for button names, icon paths and other texts are encode in Base64 strings as the first trace line for MAIN:ButtonDemo shows. To switch off tracing mode use:
        (gs:set-trace nil)
 
Even if trace mode is switched off, wrong or missing parameters are still messaged by newLISP-GS in a small message box. After such an error the application and guiserver will exit. Unknown commands will be ignored. Functions which are not applicable to certain widgets will also pop up an error message box. In certain situations a function will have no effect, e.g. gs:set-size or gs:set-color sometimes do not have an effect, depending on how a widget is configured or depending on the layout which hosts the widget. Sometimes the platform look-and-feel overwrites colors.

Event handlers

For most widgets, event handlers must be defined. Sometimes an event handler is not required. In this case specify 'gs:no-action as the event handler symbol. When developing programs it is useful to watch the event handler first before coding for it. This can be done easily by printing out event parameters:
 (gs:button 'aButton 'abutton-handler "press")
 (define (abutton-handler id)
     (println id))
 
Sometimes the same event handler function is attached to several widgets' keyboard or mouse events. Some of these events receive a greater number of parameters. There are two easy ways to discover the nature of an event:
 (define (the-handler)
     (doargs (p)
         (println "->" p)))
 
The other method looks at the source of the event as it was transmitted by the newLISP-GS. This is useful to recognize the data types used in the event:
 (define (the-handler)
     (println gs:event))
 
All text from text fields are received as base64-encoded strings. E.g. the text: "Hello World" would be received as: "SGVsbG8gV29ybGQ=":
 (gs:text-field 'TextField 'textfield-handler)


(define (textfield-handler id text) (printnl id ": " (base64-dec text)))
When the text "Hello World" is entered in the text field, the following output would be generated:
 TextField: "Hello World"
 
In case the ESC key is pressed in the text field, the event handler would report nil for the text field. A handler should therefore always check text for string contents before trying to apply the base64-dec function on it.

Mapping or applying gs:xxx functions

Like any newLISP functions, gs:xxx functions can be mapped or applied