LOGOesque extension to Language::SIMPLE - Feature creep diverts attention.

In an attempt to standardise vector graphical operations in GUIDeFATE (the world's simplest GUI designer) across different back-ends and keep things simple, a little diversion was needed. For a standard vector drawing one might use the computationally cumbersome SVG format directly and draw that on the widget. The problem is that one needs to be able to manipulate the graphics easily and AFTER deployment. I needed to script the creation of the drawing. Now lots of applications use a script language of their own, e.g. gnuplot, matlab, Kalgebra, R etc, so clearly this is a useful functionality on its own. What would be also useful is a portable scripting platform. This platform could serve my purpose, but being modular, could be easily repurposed for other applications.

Enter Language::SIMPLE (not yet on CPAN), the Simple Integrated Modular Programming Language Experiment, extended it with a LOGO to SVG translator. Dubious, I know, and vastly more powerful SVG and DOM modules exist already. But the main strength of Perl has been its ability to parse and manipulate textual data...data such as an SVG file or a script that generates that file. And the goal of this utility would have been to generate complex graphics from simple scripts, the scripts themselves potentially being generated programmatically. These graphics could then be loaded into a widget for display. Sure, the goal is not to be Inkscape, but to provide a reasonably usable set of textual graphical commands that could be scripted to create fairly complex vector imagery in a portable format, and integrateable into a GUI.

The architecture maybe could look something like this:- Now I am not sure the best way to do this. The modules are application specific. The modularity currently comes from using a do statement:-

   # $file is the extension file and contains the *contents* of a hash
   #  this hash is then inserted into %extensions  
   my %extension=do $file or die "Failed to load extension in $file $!";
   foreach my $thingy (keys %extension){
       $extensions{$extName}{$thingy}=$extension{$thingy};
   }

This loads the module which is structured as the contents of a hash. The current version of logo.ext supports creating lines, poly-lines, polygons, paths, circles, rectangles, text, colours and fills using LOGO-esque commands. SIMPLE already offers variable definition, arithmetic and some trigonometric functions along with loops, conditional branching. So it is now relatively trivial to draw images on the screen, whether it is the graphical explanation diagram above, or some random flowers below, and either save an SVG file, or insert into a widget (e.g. in a GUIDeFATE application, with any of its back-ends: Tk, Qt, GTK, Wx, and who knows, possibly Win32 etc)

random-flowers.png

Certainly it was not the intention to keep adding features to the extension, rather than focusing on GUIDeFATE. But it has been relatively simple to add commands, and I do hope to add groups, patterns and transforms. Animation should be possible thoughI am certain the performance is not going to be great, (unlikely to be able to recreate Asteroids or Elite). Adding limited 3D graphics like OpenSCAD would be another interesting diversion.

One thing for certain, testing SIMPLE and the logo extension has been made much easier because of the ability to rustle up a quick and dirty GUI application using GUIDeFATE. Which reminds me, I do need to get back to fixing GUIDeFATE proper. But few more tweaks first...

Language::SIMPLE - The Portable Integrated Scripting System

Introducing SIMPLE

SIMPLE is an experimental attempt to integrate end user scripting into Perl applications. It actually stands for Simple Integrated Modular Programming Language Experiment. The idea is that an application one develops might allow an end-user to run scripts they have made, in a custom language targeting the application's operations. Sounds silly? A script parsing utility written in another scripting language? I do a lot of silly stuff.

Some time ago, IpiGears1.jpg attempted to use a Raspberry pi for robotic and other IO applications. To save time and allow for flexibility, I had developed piGears, a scripting tool that could handle the GPIO and also have some basic flow control as well as support for I2C devices. It had been useful for my experiments with electronics, but was a rather niche utility.

Fast forward a few years and I am working on GUIDeFATE (probably the world's simplest GUI designer). I wanted a way to integrate drawing vector images to a canvas and manipulating them, and perhaps exporting them. GUIDeFATE was designed to handle a number of back-end graphical toolkits, and each had had quite different ways of handling the canvas.

Now, I confess, my coding skills are rather mediocre. Complex graphical manipulations would require a certain degree of struggling from me. But all the existing backends for GUIDeFATE can potentially handle SVG. If only I could create a way for the user to produce SVG graphics simply...

I realised I could rejig the ancient code I had written to make a more generic scripting module. All this module would need to do is to be a script interpreter allowing simple variables, subroutines and flow control, onto which anyone could bolt on customised commands and bingo your end-user can control robots, draw pictures programmatically or do anything, Now does that make sense? For many, probably not. But if you were going to parse a text script, the best language to do that in is probably Perl.

Enter Language::SIMPLE. It contains elements necessary to make a programming language without actually any components that make the programming language do anything useful. It can parse a set of instructions. It understands some variables, although technically all its variables are global. It understands subroutines, some limited flow control and code folding. With a little bit of flesh on this skeleton more sophisticated tasks can be performed from end-user scripts. SIMPLE is not on CPAN, and wont be at least until version 0.05, and only if there is some demand for such a utility. With the demo extension it is trivial to make a vector drawing program using LOGO-esque scripts.

Screenshot from 2018-08-29 23:02:57.png

Simple Linux Screenshot Application in Perl

Shutter, a powerful application for taking screenshots is possibly soon to be removed from Debian, taking with it the last desktop Perl application in that ubiquitous distro. That is a shame, but there is hope, I guess, some brave soul with take up the effort required to make it fit with GTK3s new APIs. That person is not going to be me. I don't have the skills or the time to do this. But hey, I am the author of the world's simplest GUI generator( probably). Surely it can't be that difficult to cobble together a few applications to make the world's simplest Screenshot tool? Does not need to be fancy, but needs to have a ton more features than the basic Screenshot application in Ubuntu, and be generally useful for day to day use even as a proof of concept.

Requirements

  1. Must be able to do everything that the built-in screenshot application does: -capture screenshots, save the images, and copy to clipboard.
  2. Add-on an external editor to annotate the captured images
  3. Delayed image capture
  4. Extract multiple application window captures, not just the active window
  5. (Animated screen captures e.g. to generate tutorials)
  6. (Add web camera support)

The first 4 I have been able to do relatively easily, using Imager::Screenshot, File::Copy, and a few external X11 tools: - xprop (included by default in Ubuntu) and xclip (needed sudo apt-get install xclip to install, adds clipboard functionality).

Collecting Window IDs and Names of the frame

A couple of ways to get window Ids on X11, of which xprop comes already installed in Ubuntu.

my $windowList= `xprop -root|grep ^_NET_CLIENT_LIST`;
my @winIds=$windowList=~m/(0x[0-9a-f]{7})/g;

xprop also gives us a way of getting the names of the windows

my $name=`xprop -id $id|grep '^WM_NAME(STRING)'`;
       $name=~s/WM_NAME\(STRING\) =//;
       $name=~s/\"//g;
       chomp $name;

Capturing the screenshot

Imager::Screenshot takes, would you believe, screenshots. Passed with a window ID it will capture the contents of the frame. If we know the window Ids of all the windows we could create a hash containing all the screens. While it is possible to include window decorations with the Winodws variant of Imager, this appears not to be possible for Linux. Nevermind...the code is simple.: -

my %images=map($_ => screenshot(hex $_) @winIds ;

In practice this takes a while if there are are many windows. Better to to these as and when needed.

Saving to clipboard

Now I know there is a module called Clipboard. I presume this uses xclip, itself, and as I know there is only one line that needs it, it is easier to install just xclip and : -

  system("xclip -selection clipboard -t image/png -i $workingDir.$workingFile ");

Wrapping it up with a GUI

It is trivial to set up this with GUIDeFATE, to provide all the functionality and much more in little more than 100 lines of code. Using GUIDeFATE means that we can use this with Qt, Gtk, Wx, or Tk. (Win32 not covered with this version, but probably not challenging to add the functionality). Connecting to GIMP is also trivial one line connected to an Edit button. A delayed capture is again trivial. As we know the names of the window, this can be displayed with the thumbnail. Now I don't imagine that this could ever replace a professional application, but as a proof of concept, this shows what can be achieved with relatively little effort. But with only a little more effort more can be achieved...e.g. the ability to generate animated tutorials. I am just thinking of how this might look in action...

Screenshot

This is the result of a full screen grab containing another running screen grabber (using Tk back end) grabbing the contents of the frame of another application... screenshot of screenshot in action.png

Ducktaping The Internet To The Desktop

Simple desktop applications are generally not what one considers a Perl specialization. Its expertise lies in generating processing and transforming textual data, hence its use in the web, and in tools like GUIDeFATE. This 'duct tape' manages to parse text, extracting relevant data, and absorbing information and producing a meaningful output efficiently. Displaying this output in a desktop application shouldn't be too difficult.

Challenge accepted

Not long ago I was inspired (by Ron Savage) to demonstrate ways of extracting data stored in databases with web front ends, merging contents of different sources of data and presenting it to the user, optionally making this data available offline in a local database. Should be possible to do this for the desktop user via graphical interface using GUIDeFATE. Specifically I wanted extract taxonomic information about plants, a field I have zero knowledge about. The Plants List is a useful resource with all plant species listed to anyone with a browser. Getting the list of all accepted and unresolved families and genera is trivial...use LWP::Simple and parsing the webpage form get ('http://www.theplantlist.org/1.1/browse/-/-/)' ) . From this, extracting species is a minor variation on the theme.

Wikipedia is another useful textual resource with images. From the genus or species being viewed, identifying any images on wikipedia is a mere case of generating a prospective URL, LWP::Simple::getting the source again, and using regular expressions to find the relevant section. I suspect that someone has a module that allows to navigate the HTML more elegantly rather than I have done, but as a proof of concept, this crude measure yields reasonable results.

All these can allow a simple desktop application to be developed using the rough and ready GUIDeFATE. The application allows you to search the entire Plants List directory, keeping a local cache of discovered data, and similarly searching for images from wikipedia (and keeping a copy of the images as well), to reduce the load on the respective servers).

Creating a GUI Interface

Straightforward using GUIDeFATE, of course making some allowances for the limited widget options.

use strict;
use warnings;
use GUIDeFATE;
# <  Initialise other modules and variables here >
my $window=<<END;
+-------------------------------------------+
|T The Plants List App                      |
+M------------------------------------------+
|  {Refresh Data} dd/mm/yy                  |
|  [                         ] {Search}     |
|  {Angiosperms  } 000   {Gymnosperms} 000  |
|  {Pteridophytes} 000   {Bryophytes } 000  |
|      No item on list                      |
|  +T-----------------+  +I--------------+  |    
|  |                  |  |               |  |
|  |                  |  |               |  |
|  |                  |  |               |  |
|  |                  |  |               |  |
|  |                  |  |               |  |
|  +------------------+  +---------------+  |
|  {<} {  Explore } {>}  { Upload Photo  }  |
|      0000 of 0000                         |
|  www.theplantlist.org     wikipedia.org   |
+-------------------------------------------+
END

my $backend=$ARGV[0]?$ARGV[0]:"web"; # allow command line backend selection
my $assist=$ARGV[1]?$ARGV[1]:"q";     # allow command line option selection
my $gui=GUIDeFATE->new($window,$backend,$assist);
my $frame=$gui->getFrame()||$gui;

# <  other code to be run before GUI activated  >

$gui->MainLoop()

# < rest of code >

Then adding LWP, websearch and data extraction, gives you an app like this.Qt_plantslist.png

Ducktaping the Web to a Websocket interface.

Well the real motivation for the initial challenge was to stop reinventing wheels that already work well, using clever tools like Mojolicious and other fantastic web frameworks. Can this work as a WebApp through GUIDeFATE? Apparently so, and in pure Perl. A few bugs apart, the webapp counterpart of the desktop application seems to work pretty much the same as the Desktop application. From GUIDeFATE version 0.11, setting the domain, listening port are both now possible, though still defaulting to localhost:8085. A new server is created which identifies an available listening port and a new client that survives losing focus. This makes it possible to have multiple different webapps being served and tested at the same time. WebSocket plantslist.png

So there you have it. I am afraid there are still a few bugs to squash here, and most significantly I have failed in my attempt to rationalise the position of GUIDeFATE and its slave modules in a suitable namespace. But I will next aim to add a couple of more widgets..., web links, on/off buttons, check boxes and sliders are on my list, and I suspect these will be required for the last GUI back-end to be added to the already existing Wx, Tk, Gtk, Qt, Win32 and HTML/ WebSocket backends.

Websocket Extension for GUIDeFATE - Dialogs and File Operations

GUIDeFATE, your favourite Quick-and-Dirty GUI designer for newbies is now acquiring a Web-socket interface. Now this is certainly not capable of competing with those genius applications Mojolicious, Catalyst, Dancer etc. Having only discovered Web-sockets a few weeks ago my yield is going to be decidedly sketchy. Of course a desktop interface is quite different to a web app...the machine running the interface is the same as the one the user is sitting at, and the program running the graphical output is the same as the one that is handling user interactions. When there is a client and server involved, a certain of communication is required between the two, both must of course be able to understand each other, even though they may be coded in different languages. GFweb (GUIDeFATE's Web-socket module) handles 1) the generation of the user interface 2) the initiation of a listening socket, 3) handles the communications between the two.

Dialog/Message boxes over websockets

So in the previous iteration of the GFweb we managed simple comms, button presses and interface updates. Things like the calculator and Rock-Paper-Scissors-Lizard-Spock work well. Buttons are connected to functions on the server, and each function completes an update to the state of the client immediately. Dialog boxes and File operations have been more tricky for me to implement. In the desktop modules it has been possible to call a function that triggers a dialog box and that function that triggers the dialog box returns the result...

 # function showDialog returns the result of the dialog box,
 # so can be inserted directly into, say, an if statement e.g. 

 if($frame->showDialog("Sure?",
    "This will wipe existing text...proceed?",
    "OKC","!")){ etc.

Now there probably is an easy way to do this in frameworks like Mojolicious etc. But as I have taken up wheel re-inventing, and already have started learning about Net::Websocket::Server, I have to figure out how to make a comparable interaction. This minimalist server can not trigger the dialog box and then proceed according to the result of that input. At least I have not figured out how to do this. So while under normal operations one triggers the client to create the dialog box first waits for user response and reacts to it. in the web app form, the routine that triggers the the dialog box and the one that reacts to it are distinct. The solution? Before triggering the dialog box, the programmer defines potential responses, by writing appropriate routines, and inserting these into a dispatch hash table. It is only after this point that the dialog box is triggered. The server later reacts to the actions of the user when announced by the client.

# the following lines add actions to each potential response to
# the Dialog.  Allowed responses Ok, Cancel, Yes, No and is
# defined by the parameter in showDialog e.g. OKC= Ok and Cancel,
# YNC is Yes No and Cancel
$frame->dialogAction(  "OK",       # action if ok clicked
     sub{$frame->appendValue("TextCtrl1","\nClicked OK\n"    )   } );
$frame->dialogAction(  "Cancel",   # action if cancel clicked
     sub{$frame->appendValue("TextCtrl1","\nClicked Cancel\n")   } );
# now trigger the dialog box
$frame->showDialog("The Dialog Title",
                   "The dialog Message goes here",
                   "OKC","!");

File interactions

Handling files is another issue. So a file selector box is relatively easy to trigger, the "onchange" parameter can then be used trigger the server to be ready to receive a file, and then the client proceeds to send the file as binary data. Simple.

Websockets can do binary transfers, but while the websocket protocol seems to allow very large files, with Net::Websocket::Server I could only transfer files less than 64k for some reason or the other. There is probably a way to increase the maximum transfer size. But the solution I did eventually was to create a BinaryBuffer object in JavaScript that takes the file, splits it into 64,000 byte chunks and handles the handshaking with the server until the file is reassembled on the server. Here is the screen capture log of the transfer process: -

Websocket File upload.png

Immediately after the file is loaded, the dispatch table is again queried to allow any routines that need to follow after file has been uploaded. The code is as follows, as before predefining actions for each of the potential reponses before triggering the file selector: -

# the following allows the user to upload a file to the server
# the server stores the file in a folder called dataFiles in the
# directory of the running application
$frame->dialogAction(  "Cancel",  # action if cancel clicked
     sub{$frame->appendValue("TextCtrl1","\nClicked Cancel\n")   } );
$frame->dialogAction(  "File",    # action to run after file loaded.
     sub{  
         # In this example add the filename to the text box
         # and set the Imagepanel to have this picture
        my $file=shift; #the name of the file is passed as parameter
        $frame->appendValue("TextCtrl1","\n Loaded File: $file \n"),
        $frame->setImage("Image2","dataFiles/$file")
     }  );
 # now trigger the file selector dialog box
$frame->showFileSelectorDialog("Pick a picture File",1,"");

File downloading is decidedly easier...an <a href="file-to-download" download>DOWNLOAD </a> sorts it out.

Still a bit of work to go before I put it on CPAN...not least of which is that I wish to create a Gardening Database viewer. The code is available in the test folder. I want to allow the developer able to define the listening port/host (currently localhost and 8085...useless apart for testing purposes) and also fix my implementation (currently generates an HTML file followed by a call to the system browser to load that HTML while the server is running in the background) so that it detects whether on localhost of called from across the network. I also need to start rethinking the namespaces of GUIDeFATE's accessory modules as pointed out by grinnz on reddit...maybe too late. I have tried shifting things in my setup, can't seem to get things working when I do.

Now I know what you are thinking..."Why on earth bother?". Sure this is crude, probably not very secure, and pretty deficient compared to most widely used frameworks. The answer is simple. GUIDeFATE is simple. It is sort of WYSIWIG, and will allow someone with little or no knowledge of graphical back-ends or HTML or Websockets to create a quick-and-dirty GUI application in pure Perl.